<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[OpenGenus IQ: Learn Algorithms, DL, System Design]]></title><description><![CDATA[OpenGenus IQ, an open-source Computer Science Publication House, is driven by 2500+ BSc/MSc/PhD holders globally, exploring Algorithms, Deep Learning, System Design, and more since 2017.]]></description><link>https://iq.opengenus.org/</link><image><url>https://iq.opengenus.org/favicon.png</url><title>OpenGenus IQ: Learn Algorithms, DL, System Design</title><link>https://iq.opengenus.org/</link></image><generator>Ghost 1.25</generator><lastBuildDate>Mon, 20 Apr 2026 07:17:59 GMT</lastBuildDate><atom:link href="https://iq.opengenus.org/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[AI Engineer's Silicon Cheatsheet: Must have book for AI Engineers and Researchers]]></title><description><![CDATA[<div class="kg-card-markdown"><p>The book &quot;<strong>Artificial Intelligence: AI Engineer's Cheatsheet: Silicon edition</strong>&quot; is the only book you need to master AI and ML concepts to become a ML Engineer or ML Researcher.</p>
<p>Get your copy at: <a href="https://amzn.to/46R7Ao5">AI ENGINEER SILICON CHEATSHEET</a></p>
<p>The book will give you the real research and engineering knowledge</p></div>]]></description><link>https://iq.opengenus.org/ai-engineers-silicon-cheatsheet/</link><guid isPermaLink="false">68dcfb90b31fb73e7be32d9b</guid><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[Deep Learning]]></category><dc:creator><![CDATA[Aditya Chatterjee]]></dc:creator><pubDate>Wed, 01 Oct 2025 20:08:19 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>The book &quot;<strong>Artificial Intelligence: AI Engineer's Cheatsheet: Silicon edition</strong>&quot; is the only book you need to master AI and ML concepts to become a ML Engineer or ML Researcher.</p>
<p>Get your copy at: <a href="https://amzn.to/46R7Ao5">AI ENGINEER SILICON CHEATSHEET</a></p>
<p>The book will give you the real research and engineering knowledge you lack. No AI will replace you if you have this skill. For theoretical knowledge, search algorithms were enough.</p>
<p>This book covers all major topics that you must understand to build a practical deep understanding of state-of-the-art (SOTA) AI. Some of the topics include:</p>
<ul>
<li>Design of <strong>AI systems (MLSys) and LLM serving</strong>. Foundation of systems like vLL, SGLang. Optimizations that help OpenAI serve over 900M users weekly like Prefill Chunk.</li>
<li>Core <strong>LLM architecture</strong> and operations like Attention with variants like FlexAttention, FlashAttention and more.</li>
<li>Core <strong>Deep Learning optimizations</strong> like Quantization.</li>
<li>Architecture and optimization techniques of AI processors like GPU, TPU, Gaudi and CPU (x86 + ARM).</li>
<li>Core Intuitive Understanding that helps you understand the global AI race and direction and helps you to jump into AI discussions.</li>
</ul>
<p>On completing this book, you will be ready:</p>
<ul>
<li>To clear interview opportunities at High-Tech companies like Meta, Google, xAI and Foundational AI startups like Mixtral and Perplexity.</li>
<li>Be able to conduct your own independent AI research.</li>
<li>Be able to do quick calculations of various AI/LLM requirements.</li>
<li>Deep insights into everything AI.</li>
<li>Join AI discussions on World Politics or Future of AI.</li>
</ul>
<p>This book is for:</p>
<ul>
<li>Students and developers preparing for Coding Interviews specifically for Machine Learning/Deep Learning/GenAI positions.</li>
<li>Experienced developers who wanted to revise their Deep Learning skills.</li>
<li>Students who need a coding sheet to revise DL/AI/ML topics quickly.</li>
</ul>
<p>Get started with this book and change the equation of your career.</p>
<p>Book: Artificial Intelligence: AI Engineer's Cheatsheet: Silicon edition<br>
Author (1): Seymour Boris Papermaster<br>
Published: September 2025 (Edition 1)</p>
</div>]]></content:encoded></item><item><title><![CDATA[Random Number Generators: The Core of Online Gambling Fairness]]></title><description><![CDATA[When players spin the reels of an online pokie or place a bet at a digital blackjack table, they expect one thing above all else: fairness. That sense of trust is made possible by Random Number Generators (RNGs), the unseen engines running behind every legitimate online casino game.]]></description><link>https://iq.opengenus.org/random-number-generators-the-core-of-online-gambling-fairness/</link><guid isPermaLink="false">68c2ea9edc3e9546e28d47a8</guid><dc:creator><![CDATA[Abdesselam Benameur]]></dc:creator><pubDate>Thu, 11 Sep 2025 18:19:26 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>When players spin the reels of an online pokie or place a bet at a digital blackjack table, they expect one thing above all else: fairness. That sense of trust is made possible by Random Number Generators (RNGs), the unseen engines running behind every legitimate online casino game. These algorithms are responsible for ensuring that each spin, card draw, or dice roll is unpredictable and independent from the last. Without RNGs, the credibility of the entire online gambling industry would collapse. I've spent years studying how casinos operate, and in my experience, the platforms that are most transparent about their RNG systems - such as <a href="https://uptown-pokies.online/en-au/">https://uptown-pokies.online/en-au/</a> create an environment where players can spin with confidence, knowing that fairness isn't just promised, but built into every outcome. By embracing certified RNGs, these casinos prove that chance, not manipulation, determines whether you win or lose.</p>
<h2 id="howrngsactuallywork">How RNGs Actually Work</h2>
<p>At its core, an RNG is a piece of software that generates long sequences of numbers at lightning speed. Each number corresponds to a potential outcome in the game - such as which reel symbols appear, which card is dealt, or where the roulette ball lands. The system ensures that every result is independent from the last. That's why even if you've had ten spins without a win, the next spin is not &quot;due&quot; for a payout; it's just as unpredictable as the first.</p>
<p>Most online casinos use two types of RNGs:</p>
<ul>
<li><strong>Pseudo-RNGs</strong>: Software-driven, relying on complex algorithms and seed values. These are the most common in pokies and digital table games.</li>
<li><strong>True RNGs</strong>: Hardware-based, often using natural phenomena (like electronic noise) to generate randomness. These are less common but considered the gold standard. As an expert tip, I always advise players to look for platforms that submit their RNGs to independent auditors, such as eCOGRA or iTech Labs. These certifications prove that the system has been tested for genuine randomness and fairness.</li>
</ul>
<h2 id="whyrngsmatterforplayers">Why RNGs Matter for Players</h2>
<p>For players, the RNG is both friend and foe. It guarantees that outcomes are fair, but it also removes any illusion of control. No strategy can influence when a jackpot drops or when a winning hand arrives. This may sound frustrating, but it's what protects the integrity of the game.</p>
<p>In practical terms, this means:</p>
<ol>
<li><strong>Every spin is unique</strong> - Past results don't affect future outcomes.</li>
<li><strong>Payout rates are statistical</strong> - Over thousands of plays, the advertised RTP (Return to Player) becomes<br>
accurate.</li>
<li><strong>Fairness is constant</strong> - Whether you bet small or go all in, the RNG doesn't discriminate.</li>
</ol>
<p>Understanding this helps you approach online gambling with the right mindset. Rather than chasing patterns, focus on bankroll management, choosing games with strong RTPs, and playing for entertainment first.</p>
<h2 id="rngsandresponsiblegambling">RNGs and Responsible Gambling</h2>
<p>One of the underappreciated roles of RNGs is how they support responsible gambling. Because outcomes cannot be predicted or manipulated, RNGs discourage unhealthy &quot;chasing losses.&quot; For example, if you lose several rounds in a row, it doesn't mean a win is around the corner. Accepting this truth helps players set realistic expectations.</p>
<p>From my perspective, the best players aren't those who try to beat the RNG - they're the ones who understand it. By recognizing that every spin is independent, you learn to enjoy the unpredictability without falling into the trap of superstition.</p>
<h2 id="thefutureofrngsinonlinecasinos">The Future of RNGs in Online Casinos</h2>
<p>With the rise of blockchain technology and AI, RNGs are evolving. Some casinos are experimenting with transparent &quot;provably fair&quot; systems, where players can verify the randomness of each outcome in real time. This extra layer of transparency could redefine how trust is built in online gambling.</p>
<p>Meanwhile, AI is being used to monitor RNG performance, ensuring that systems remain secure and resistant to hacking attempts. For players, this means the fairness of online pokies and casino games will only grow stronger in the future.</p>
<h2 id="finalthoughts">Final Thoughts</h2>
<p>Random Number Generators are the backbone of online casino fairness. They ensure that when you spin, bet, or withdraw your winnings, the outcome is governed by chance, not manipulation. For players who want both entertainment and trust, choosing platforms that emphasize certified RNG systems - such as Uptown Pokies - is essential. By understanding how these systems work, you gain peace of mind and can focus on enjoying the excitement that makes online gambling such a global phenomenon.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Blockchain Nodes Demystified: A Technical Overview]]></title><description><![CDATA[In the ever-evolving world of decentralized technologies, understanding the core infrastructure behind blockchain systems is essential.]]></description><link>https://iq.opengenus.org/blockchain-nodes-demystified-a-technical-overview/</link><guid isPermaLink="false">68558c82f43c812aadeb9e60</guid><category><![CDATA[Blockchain]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Abdesselam Benameur]]></dc:creator><pubDate>Fri, 20 Jun 2025 18:30:49 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>In the ever-evolving world of decentralized technologies, understanding the core infrastructure behind blockchain systems is essential. Among the most critical components of any blockchain network are nodes. While frequently mentioned, nodes are often misunderstood. This article provides a technical overview of blockchain nodes, demystifying their role, types, and operational significance within a distributed ledger environment.</p>
<h2 id="whatareblockchainnodes">What Are Blockchain Nodes?</h2>
<p>At its simplest, a node is any device—typically a computer—that participates in the blockchain network. Nodes communicate with each other to propagate transactions and blocks, verify information, and maintain a copy (partial or full) of the blockchain ledger.</p>
<p>These nodes work together to maintain the integrity, security, and decentralization of the network.</p>
<h2 id="typesofblockchainnodes">Types of Blockchain Nodes</h2>
<p>Blockchain nodes vary depending on their roles and responsibilities. Here are the most common types:</p>
<h2 id="1fullnodes">1. Full Nodes</h2>
<p>Full nodes are at the heart of <a href="https://builtin.com/blockchain">a blockchain network</a>. They download and store the whole history of the blockchain and independently verify every transaction and block. Bitcoin and Ethereum rely heavily on full nodes to maintain network consensus. These nodes enforce the rules of the protocol and reject invalid data.</p>
<h2 id="2lightweightorspvnodes">2. Lightweight (or SPV) Nodes</h2>
<p>Simplified Payment Verification (SPV) or light nodes don’t store the full blockchain. Instead, they download only block headers and rely on full nodes to retrieve transaction data. SPV nodes are commonly used in mobile wallets and applications where full verification is unnecessary or resource-intensive.</p>
<h2 id="3minernodes">3. Miner Nodes</h2>
<p>These are specialized nodes that contribute computational power to validate transactions and create new blocks. While all miner nodes are full nodes, not all full nodes are miners. Mining nodes solve complex mathematical problems as part of the consensus mechanism (e.g., Proof of Work) to add new blocks to the blockchain.</p>
<h2 id="4masternodes">4. Masternodes</h2>
<p>Some blockchains, like Dash, use masternodes—full nodes with enhanced responsibilities such as enabling instant transactions or private transfers. Masternodes often require staking a significant number of coins to operate and receive rewards in return.</p>
<h2 id="5archivenodes">5. Archive Nodes</h2>
<p>Particularly in networks like Ethereum, archive nodes store everything that full nodes do, plus all intermediate states. While not essential for most users, archive nodes are crucial for network analytics, debugging, and forensic applications.</p>
<h2 id="whynodesmatter">Why Nodes Matter</h2>
<p><a href="https://www.ccn.com/education/crypto/bitcoin-full-nodes-light-nodes-explained/">Nodes are vital to decentralization</a>. Without nodes distributed across multiple jurisdictions and operated by diverse participants, a blockchain risks becoming centralized and vulnerable to control or censorship. Nodes also play a crucial role in ensuring the network is fault-tolerant and resilient to attacks or outages.</p>
<p>Furthermore, nodes are essential for maintaining consensus. By independently validating and broadcasting transactions and blocks, nodes ensure that all participants have a consistent view of the blockchain’s state.</p>
<h2 id="settingupanode">Setting Up a Node</h2>
<p>Running a node involves downloading the appropriate blockchain client software, syncing with the network, and allocating sufficient resources (CPU, memory, and storage). While this may sound daunting, improvements in hardware and software have made it more accessible than ever to run your own node—even on a virtual private server or cloud infrastructure.</p>
<p>For a more detailed guide on what blockchain nodes are and how they function, check out this comprehensive article on <a href="https://contabo.com/blog/blockchain-nodes-explained/">blockchain nodes</a>.</p>
<h2 id="summingup">Summing Up</h2>
<p>Blockchain nodes are foundational to the operation and security of decentralized networks. Understanding their technical roles helps demystify the architecture of blockchains and empowers individuals to participate more actively—whether as users, developers, or operators. As blockchain technology continues to mature, nodes will remain a cornerstone of decentralized digital infrastructure.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Run Llama3.1-8B (LLM) on DigitalOcean CPU droplet]]></title><description><![CDATA[In this guide at OpenGenus.org, we present the steps to setup the minimum required DigitalOcean CPU droplet, download Llama3.1-8B-Instruct model, prepare the script to run it on a sample input and generate the output. The computation time can vary from 2 to 10 minutes (or beyond).]]></description><link>https://iq.opengenus.org/llama-on-digitalocean-cpu-droplet/</link><guid isPermaLink="false">6821a5445c14bd5ba00f9b09</guid><category><![CDATA[Deep Learning]]></category><dc:creator><![CDATA[Aditya Chatterjee]]></dc:creator><pubDate>Thu, 15 May 2025 16:58:06 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><br>
<p>Llama is an <strong>open-source pre-trained LLM</strong> released by Meta which can be used to run ChatGPT like prompts locally on CPU or GPU. Llama comes in different sizes like 1B parameters, 8B, 70B and 405B. The capability of the LLM increases with the number of parameters. This is preferred to OpenAI API because using Llama locally gives more native support.</p>
<p>The 8B variant of LLM performs reasonably well and can ask moderate level questions and write simple code as well. This is something 1B variant cannot perform.</p>
<p><strong>LLMs are usually too large to run on CPU</strong> due to limited memory and compute power and GPU are expensive.</p>
<p>If you wish to <strong>test Llama on a CPU server</strong> due to budget limitations, you can <strong>test Llama 3.1 8B model on DigitalOcean CPU droplet</strong> with a nominal cost of <strong>$86 per month</strong>. On the other hand, using a NVIDIA <strong>GPU</strong> on DigitalOcean to run it or larger versions of Llama 3.1 or 3.3 may cost <strong>over $90 per day</strong> (30X more).</p>
<p>In this guide at OpenGenus.org, we present the <strong>steps to setup the minimum required DigitalOcean CPU droplet, download Llama3.1-8B-Instruct model, prepare the script to run it on a sample input and generate the output</strong>. The computation time can vary from 2 to 10 minutes (or beyond) depending on the input prompt length.</p>
<h3 id="tableofcontents">Table of contents:</h3>
<ul>
<li>Minimum requirements to run Llama3.1-8B</li>
<li>Minimum DigitalOcean CPU droplet needed</li>
<li>Steps to prepare your droplet to run Llama on CPU</li>
<li>Script to run LLM with an input prompt</li>
<li>Run the LLM script on CPU</li>
</ul>
<h2 id="minimumrequirementstorunllama318b">Minimum requirements to run Llama3.1-8B</h2>
<p>Minimum requirements to run Llama3.1-8B or any LLM:</p>
<ul>
<li><strong>16GB RAM</strong> required for 4096+ tokens to be run.</li>
<li>Llama3.1-8B requires a <strong>minimum of 10GB RAM</strong> to load into memory. This involves KV cache. With the lower cache, the model fails to perform inference.</li>
<li><strong>SSD memory of 20GB</strong> (Llama3.1-8B Model files are of 16.4GB)</li>
</ul>
<h2 id="minimumdigitaloceancpudropletneeded">Minimum DigitalOcean CPU droplet needed</h2>
<p>Specification of the most economical DigitialOcean CPU droplet required to run Llama 3.1 8B model:</p>
<ul>
<li>Machine type: Basic</li>
<li>CPU type: Premium AMD</li>
<li>vCPUs: 4</li>
<li>RAM: 16GB</li>
<li>SSD: 80GB</li>
<li>Transfer: 8TB</li>
<li>Price: $84 per month (As of May 2025)</li>
</ul>
<p>Once the plan is acquired, an <strong>IP Address</strong> is assigned and you have to set the <strong>password</strong>.</p>
<h2 id="stepstouseyourdroplettorunllamaoncpu">Steps to use your droplet to run Llama on CPU</h2>
<h3 id="installmobaxterm">Install MobaXTerm</h3>
<ul>
<li>
<p>Install the free version of <a href="https://mobaxterm.mobatek.net/download.html">MobaXterm</a> to connect to the DigitalOcean droplet  using terminal.</p>
</li>
<li>
<p>Click on new Session</p>
</li>
<li>
<p>Select the SSH Client type<br>
<img src="https://iq.opengenus.org/content/images/2025/05/select-client-type.png" alt="select-client-type"><br>
<small><center>Figure: MobaXterm: SSH client</center></small></p>
</li>
<li>
<p>Enter the <strong>IP Address</strong> in the Remote Host field and the <strong>username</strong> as got from DigitalOcean.<br>
<img src="https://iq.opengenus.org/content/images/2025/05/session-settings.png" alt="session-settings"><br>
<small><center>Figure: MobaXterm: IP address and userame</center></small></p>
</li>
<li>
<p>Now the Session is created</p>
</li>
<li>
<p>Enter the password in the terminal to run the model.</p>
</li>
</ul>
<h3 id="getaccessofllama318bfrommeta">Get access of Llama3.1-8B from Meta</h3>
<p>Llama is a series of LLM from Meta (formerly known as Facebook).</p>
<ul>
<li>Request Access to Llama3.1 from <a href="https://www.llama.com/llama-downloads/">Meta</a></li>
<li>Once the Request is approved, the unique URL will be shared through email.</li>
<li>Install Llama CLI:</li>
</ul>
<pre><code class="language-c">pip install llama-stack
</code></pre>
<ul>
<li>To check the available models run</li>
</ul>
<pre><code class="language-c">llama model list
</code></pre>
<p>Output:<br>
<img src="https://iq.opengenus.org/content/images/2025/05/llama-model-list-1.png" alt="llama-model-list-1"><br>
<small><center>Figure: List of available Llama models</center></small></p>
<ul>
<li>The model that we have to download is <strong>Llama3.1-8B-Instruct</strong>.</li>
<li>Use the following command to install the model</li>
</ul>
<pre><code class="language-c">llama download --source meta --model-id Llama3.1-8B-Instruct
</code></pre>
<p><img src="https://iq.opengenus.org/content/images/2025/05/download-model.png" alt="download-model"><br>
<small><center>Figure: Download the required Llama model</center></small></p>
<ul>
<li>Now you have to provide the unique URL sent by Meta through email</li>
</ul>
<h3 id="getaccessfromhuggingface">Get access from HuggingFace</h3>
<p>Since Llama3.1-8B is a gated repository, you have to get access from <a href="https://huggingface.co/meta-llama/Meta-Llama-3-8B">HuggingFace</a>.</p>
<p><img src="https://iq.opengenus.org/content/images/2025/05/access-from-hugging-face.png" alt="access-from-hugging-face"><br>
<small><center>Figure: Access request at HuggingFace</center></small></p>
<p>Fill in the above details:</p>
<ul>
<li>
<p>To check for approval updates, click on your HuggingFace profile then go to settings -&gt; gated repository<br>
<img src="https://iq.opengenus.org/content/images/2025/05/llama-model-accepted.png" alt="llama-model-accepted"><br>
<small><center>Figure: HuggingFace: request status accepted</center></small></p>
</li>
<li>
<p>Once accepted, go to access tokens<br>
<img src="https://iq.opengenus.org/content/images/2025/05/access-token.png" alt="access-token"><br>
<small><center>Figure: HuggingFace: access token</center></small></p>
</li>
<li>
<p>Create a new token<br>
<img src="https://iq.opengenus.org/content/images/2025/05/create-new-token.png" alt="create-new-token"><br>
<small><center>Figure: HuggingFace: create new token</center></small></p>
</li>
<li>
<p>Fill in the details and select all the user permissions<br>
<img src="https://iq.opengenus.org/content/images/2025/05/create-token-details.png" alt="create-token-details"><br>
<small><center>Figure: HuggingFace: user permissions</center></small></p>
</li>
<li>
<p>Save the access token for later use (Note: this is a sample which we have deleted. You need to create your own token).<br>
<img src="https://iq.opengenus.org/content/images/2025/05/save-access-token.png" alt="save-access-token"><br>
<small><center>Figure: HuggingFace: save token</center></small></p>
</li>
</ul>
<h3 id="installnecessarylibraries">Install necessary libraries</h3>
<p>Install pip:</p>
<pre><code class="language-c">sudo apt install python3-pip -y
</code></pre>
<p>Install Huggingface, Transformers, Torch, Accelerate:</p>
<pre><code class="language-c">pip install huggingface_hub
pip install transformers
pip install torch
pip install accelerate
</code></pre>
<h2 id="scripttorunllmwithaninputprompt">Script to run LLM with an input prompt</h2>
<ul>
<li>Create a file named &quot;prompt.py&quot;:<br>
<img src="https://iq.opengenus.org/content/images/2025/05/create-prompt-file.png" alt="create-prompt-file"><br>
<br><small><center>Figure: LLM script</center></small></li>
</ul>
<p>Following is the code to start inference of your LLM (<em>we will go through the explanation of the code following it</em>):</p>
<pre><code class="language-c">from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

model_id = &quot;meta-llama/Llama-3.1-8B-Instruct&quot;

# Load tokenizer and model
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    torch_dtype=torch.bfloat16,
    device_map=&quot;auto&quot;
)

prompt = &quot;&quot;&quot;&lt;|begin_of_text|&gt;&lt;|start_header_id|&gt;system&lt;|end_header_id|&gt;

Environment: ipython&lt;|eot_id|&gt;&lt;|start_header_id|&gt;user&lt;|end_header_id|&gt;

Write code to check if number is armstrong, use that to see if the number 153 is armstrong&lt;|eot_id|&gt;&lt;|start_header_id|&gt;assistant&lt;|end_header_id|&gt;
&quot;&quot;&quot;

# Tokenize and move to model device
inputs = tokenizer(prompt, return_tensors=&quot;pt&quot;).to(model.device)

# Generate the model's response
outputs = model.generate(
    inputs.input_ids,
    max_new_tokens=128,
    do_sample=True,
    temperature=0.7,
    top_p=0.9
)

# Decode and print only the model's answer
response = tokenizer.decode(
    outputs[0][inputs.input_ids.shape[-1]:],
    skip_special_tokens=True
)
print(response)
</code></pre>
<h3 id="explanationofthescript">Explanation of the script</h3>
<p>In short, the code prompts Llama 3.1 8B to generate a program to check if the number 153 is an Armstrong number. The process involves tokenizing the input, feeding it to the model and decoding the generated response to print it.</p>
<p>This code is using the HuggingFace transformers library to interact with the LLM to generate a response for a programming task. Following is the step by step explanation:</p>
<ul>
<li><strong>Imports</strong><br>
<strong>AutoTokenizer</strong> and <strong>AutoModelForCausalLM</strong> are classes from the HuggingFace transformers library. The AutoTokenizer is used to handle tokenization (converting text into input suitable for the model), and AutoModelForCausalLM is used to load the language model (in this case, for causal language modeling, which generates text based on a prompt).</li>
</ul>
<p>torch is the PyTorch library, used for managing tensors and running models on devices like CPU or GPU.</p>
<ul>
<li>
<p><strong>Model ID</strong><br>
model_id = &quot;<strong>meta-llama/Llama-3.1-8B-Instruct</strong>&quot; specifies which model to load. It refers to a specific pre-trained model called Llama 3.1 with 8 billion parameters.</p>
</li>
<li>
<p><strong>Load Tokenizer and Model</strong><br>
The tokenizer is loaded from the specified model, which prepares the text for the model. The model is loaded with <code>torch_dtype=torch.bfloat16</code> (which reduces memory usage and improves speed on supported hardware), and device_map=&quot;auto&quot; automatically places the model on the available device (CPU or GPU).</p>
</li>
<li>
<p><strong>Prompt</strong><br>
A prompt is defined which contains a system instruction (environment: ipython) and a user request to write a program to check if the number 153 is an Armstrong number. The format uses special tokens like &lt;|begin_of_text|&gt; to mark different sections.</p>
</li>
<li>
<p><strong>Tokenize Input</strong><br>
The prompt is tokenized (converted into numerical representations) and sent to the model's device.</p>
</li>
<li>
<p><strong>Generate Model Response</strong><br>
The generate method is used to generate the model's response based on the provided input. In this case, it generates up to 128 new tokens with sampling controls (temperature=0.7 and top_p=0.9) to control the randomness and creativity of the response.</p>
</li>
<li>
<p><strong>Decode and Output the Response</strong><br>
The output tokens from the model are decoded back into text, skipping any special tokens used for processing.</p>
</li>
</ul>
<h2 id="runthellmscriptoncpu">Run the LLM script on CPU</h2>
<p>Login into HuggingFace<br>
Run the following command:</p>
<pre><code class="language-c">huggingface-cli login
</code></pre>
<p><img src="https://iq.opengenus.org/content/images/2025/05/huggingface-login.png" alt="huggingface-login"><br>
<small><center>Figure: LLM script</center></small></p>
<p>Now enter the access token<br>
<img src="https://iq.opengenus.org/content/images/2025/05/login-git.png" alt="login-git"></p>
<ul>
<li>For access to git credentials, select &quot;no&quot;.</li>
<li>Once login is successful, we will run the Python script.<br>
<img src="https://iq.opengenus.org/content/images/2025/05/login-success.png" alt="login-success"></li>
</ul>
<p>Run the command:</p>
<pre><code class="language-c">python3 prompt.py
</code></pre>
<p>Output:</p>
<p><img src="https://iq.opengenus.org/content/images/2025/05/output.png" alt="output"></p>
<p>Testing is possible in CPU, but once script is ready and you have tested on CPU with patience, you can switch to GPU to compute faster on larger number of prompts.</p>
</div>]]></content:encoded></item><item><title><![CDATA[C++ Coding Cheatsheet: GOAT edition]]></title><description><![CDATA[The book "C++: Coding Cheatsheet: GOAT edition" is the only book you need to master C++ programming concepts. The focus is on practical programming skills, design concepts and performance engineering ideas.]]></description><link>https://iq.opengenus.org/cpp-cheatsheet-goat/</link><guid isPermaLink="false">67e6dab202bed511baee463a</guid><category><![CDATA[books]]></category><category><![CDATA[C++]]></category><dc:creator><![CDATA[Jey Son Chuah]]></dc:creator><pubDate>Fri, 28 Mar 2025 17:29:40 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>The book &quot;<strong>C++: Coding Cheatsheet: GOAT edition</strong>&quot; is the only book you need to master C++ programming concepts. The focus is on practical programming skills, design concepts and performance engineering ideas.</p>
<blockquote>
<p>GOAT = &quot;<strong>G</strong>reatest <strong>O</strong>ptimizations, <strong>A</strong>bstractions and <strong>T</strong>echniques&quot;</p>
</blockquote>
<p>Read <a href="https://www.amazon.com/dp/B0F2GHQT6W?asin=B0F2GHQT6W&amp;revisionId=56e95507&amp;format=3&amp;depth=1">C++ Coding Cheatsheet: GOAT edition here for free</a></p>
<p>This book include:</p>
<ul>
<li>Chapters covering all core concepts in C++ programming, code design and optimization including:
<ul>
<li>OOP concepts, Inheritance, Composition, Singleton pattern</li>
<li>Efficient use of C++ STL for DSA</li>
<li>and much more.</li>
</ul>
</li>
<li>Each chapter is a CHEATSHEET. It includes to-the-point explanation and relevant code snippets.</li>
<li>Each concept can be covered quickly in at most 4 minutes.</li>
</ul>
<p>With this, you will be able to crack any Coding Interview easily.</p>
<p>After reading this book, you will:</p>
<ul>
<li>Master C++ programming concepts. Have a strong mental model equivalent to programming at least 10K lines of C++ code.</li>
<li>Strong implementation skills to optimize for performance.</li>
<li>Clear interviews for full-time positions at high-tech companies.</li>
</ul>
<p>This book is for:</p>
<ul>
<li>Students and developers preparing for Coding Interviews with C++ as their primary programming language.</li>
<li>Experienced developers who wanted to revise their C++ concepts.</li>
<li>Students who need a coding sheet to revise C++ topics quickly.</li>
</ul>
<p>Get started with this book and change the equation of your career.</p>
<p>Book: <strong>C++: Coding Cheatsheet: GOAT edition</strong><br>
Authors (1): <strong>Wesley Kincaid</strong><br>
Published: March 2025 (Edition 1)</p>
</div>]]></content:encoded></item><item><title><![CDATA[DL1943 Deep Learning Cheatsheet]]></title><description><![CDATA[The book "Deep Learning: DL1943 Cheatsheet: DL/AI/ML Research, Engineering, Optimization & System Design" is the only book you need to master Deep Learning (DL) concepts.]]></description><link>https://iq.opengenus.org/dl1943-cheatsheet/</link><guid isPermaLink="false">67c85f7157279a13cde8b427</guid><category><![CDATA[Deep Learning]]></category><category><![CDATA[books]]></category><dc:creator><![CDATA[Ue Kiao, PhD]]></dc:creator><pubDate>Wed, 05 Mar 2025 14:34:28 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>The book &quot;<strong>Deep Learning: DL1943 Cheatsheet: DL/AI/ML Research, Engineering, Optimization &amp; System Design</strong>&quot; is the only book you need to master Deep Learning (DL) concepts.</p>
<p>Read the book for free: <a href="https://www.amazon.com/dp/B0DWZBSKXF?asin=B0DY7SXGVV&amp;revisionId=&amp;format=4&amp;depth=2">HERE</a></p>
<p><a href="https://amzn.to/4imt9RB">Get your printed book copy of DL1943 Cheatsheet</a></p>
<img width="60px" alt="DL1943 CHEATSHEET BOOK" src="https://github.com/user-attachments/assets/dac3b924-4f9c-4ee4-9de6-64c6fb2f54c5">
<p>This book include:</p>
<ul>
<li>Chapters covering all core concepts in DL research, engineering and optimization including:
<ul>
<li>Basic concepts like Perceptron, Gradient Descent</li>
<li>All basic terms like epoch, topK and basic ops like MaxPool</li>
<li>Core techniques like INT8 Quantization</li>
<li>Deep Learning System Design (with examples)</li>
<li>Numerical Analysis concepts like INT32 IEEE754, emulating FP64 using FP32.</li>
<li>Optimization techniques across:</li>
<li>Assembly instructions like AVX512 VNNI</li>
<li>Algorithmic optimizations for DL operations like MatMul</li>
<li>Graph level operations</li>
<li>and much more.</li>
</ul>
</li>
<li>Each chapter is a CHEATSHEET. It includes to-the-point explanation and relevant code snippets.</li>
<li>Each concept can be covered quickly in at most 4 minutes.</li>
<li>Over 350 DL/AI concepts have been covered.</li>
</ul>
<p>With this, you will be able to crack any Deep Learning Coding Interview easily.</p>
<p>After reading this book, you will:</p>
<ul>
<li>Master Deep Learning/ Artificial Intelligence.</li>
<li>Clear interviews for full-time positions at high-tech companies. Good enough for:
<ul>
<li>Software Engineer 2/3, Machine Learning or Senior Software Engineer, AI/ML GenAI or ML Analyst at Google (L3/L4/L5)</li>
<li>Software Engineer, Machine Learning (E4/E5/E6) at Meta</li>
<li>Senior Deep Learning Systems Software Engineer - AI or AI Developer Technology Engineer at NVIDIA</li>
<li>Kernel Software Engineer - AI/ML GPU or Senior Machine Learning Software Engineer at AMD</li>
<li>Lead Engineer, Senior-C/C++, machine learning at Qualcomm</li>
<li>Machine Learning Engineer at Microsoft (Level 60 to 66)</li>
<li>And much more.</li>
</ul>
</li>
</ul>
<p>This book is for:</p>
<ul>
<li>Students and developers preparing for Coding Interviews specifically for Machine Learning/Deep Learning/GenAI positions.</li>
<li>Experienced developers who wanted to revise their Deep Learning skills.</li>
<li>Students who need a coding sheet to revise DL/AI/ML topics quickly.</li>
</ul>
<p>Get started with this book and change the equation of your career.</p>
<p>Book: <strong>Deep Learning: DL1943 Cheatsheet: DL/AI/ML Research, Engineering, Optimization &amp; System Design</strong><br>
Authors (2): Calder Reed, Chen Hui Fang<br>
Published: February 2025 (Edition 1)</p>
</div>]]></content:encoded></item><item><title><![CDATA[Multi-Agent Cyber-Physical Systems]]></title><description><![CDATA[So far we've been only talking about single-agent systems. However, as we attempt to model complex systems in the real world, we shall soon find that in most cases a single agent will not suffice.]]></description><link>https://iq.opengenus.org/multi-agent-cps/</link><guid isPermaLink="false">674d03a26531196fd986f4a4</guid><dc:creator><![CDATA[Sarthak Das]]></dc:creator><pubDate>Fri, 10 Jan 2025 20:21:34 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><h2 id="introduction">Introduction</h2>
<p>In a <a href="https://iq.opengenus.org/introduction-to-cyber-physical-systems/">previous article</a>, we introduced the concept of cyber-physical systems (CPS). Moving further in our journey into CPS, <strong>agent</strong> is a term we will be encountering quite a lot. So let's get that off our plate first. Simply put, an agent is an <em>autonomous entity</em> that navigates through a given <em>environment</em>.</p>
<p>In the context of CPS, we can think of an agent as an entity that interacts with the environment in a manner defined by its hybrid automaton. Consider the bouncing ball example we discussed previously. Here, the ball can be though of as the agent, and the nature of its interactions with the environment, such as free fall and rebounding off the ground, is defined by the hybrid automata of the system.</p>
<p>Clearly, so far we've been only talking about single-agent systems - where the hybrid automaton describing the agent's behaviour is as good as describing the entire system itself. However, as we attempt to model complex systems in the real world, we shall soon find that in most cases a single agent will not suffice.</p>
<p>As such, we must talk about <strong>multi-agent CPS</strong>, where the behaviour of each agent (their interactions with the environment, which comprises mainly of the other agents) is described by their own individual hybrid automaton. Then, if we wish to study the system as a whole, we must look at the collective behaviour that emerges out of these individual hybrid automata. In order to do this, we must take the help of <strong>compositional hybrid automata (CHA)</strong>.</p>
<h2 id="andwhatisacompositionalhybridautomaton">And what is a compositional hybrid automaton?</h2>
<p>Now that we are familiar with the language of hybrid automata, let us define a multi-agent CPS by describing a couple of hybrid automata - each representing a single agent in the system:</p>
<p><img src="https://iq.opengenus.org/content/images/2024/12/Screenshot-2024-12-02-071448.png" alt="Screenshot-2024-12-02-071448"></p>
<p>What does this system do? In order to understand the behaviour of the system as a whole, it is beneficial to talk first about the individual agents: the water tank, the burner, and the thermometer.</p>
<p>The tank initially has a constant temperature <em>x</em> of 20 degrees Celsius (location <em>t4</em>). Only if the burner is turned on (transition <em>ON</em>), the temperature will start to increase as the water starts heating (location <em>t1</em>). There seems to be some mechanism that caps the upper temperature limit to 100 degrees, and when this limit is reached (transition <em>B</em> to location <em>t2</em>) the heating stops. However, the burner must then be turned off (transition <em>OFF</em>) for the water to cool down naturally (location <em>t3</em>). Of course at any point during heating or cooling, we can turn the burner off or on to transition between locations <em>t1</em> and <em>t3</em>. The dynamics for the tank is described by the hybrid automaton <em>H1</em>.</p>
<p>The burner is initially switched off (location <em>b1</em>). When it is switched on (transition <em>TURN-ON</em> to location <em>b2</em>) it takes about 0.1 seconds time <em>y</em> to actually start the heating process (transition <em>ON</em> to location <em>b3</em>). Similarly, when it is switched off (transition <em>TURN-OFF</em> to location <em>b4</em>) it takes about 0.1 seconds time <em>y</em> to actually stop the heating process entirely (transition <em>OFF</em> to location <em>b1</em>). The dynamics for the burner is described by the hybrid automaton <em>H2</em>.</p>
<p><strong>Note.</strong> The <em>ON</em> and <em>OFF</em> transitions in the tank automaton have the same label as the <em>ON</em> and <em>OFF</em> transitions in the burner automaton. This is completely intentional, and this is how the agents communicate with each other. For example, when the burner sends an <em>ON</em> signal to the tank, only then the water in the tank actually starts heating. This is known as <strong>label synchronization</strong>. A multi-agent CPS may or may not exhibit label synchronization.</p>
<p>The thermometer is much simpler: it continuously measures the water temperature <em>x</em> and sends periodic signals at an interval of 0.1 seconds about whether the temperature is lower than 93 degrees (transition <em>DW93</em>), above 95 degrees (transition <em>UP95</em>) or somewhere in between (transition <em>ε</em>), based on which the managers of the water heating plant can manually switch off the burner if needed. The dynamics for the thermometer is described by the hybrid automaton <em>H3</em>.</p>
<p><strong>Note.</strong> The variable <em>x</em> of the thermometer automaton is the same as the variable <em>x</em> of the tank automaton, so that the thermometer can be used to directly monitor the water temperature of the tank. This is another way for the agents to communicate with each other and is known as <strong>shared variables</strong>. A multi-agent CPS may or may not exhibit shared variables.</p>
<p>When considered together, these three components completely describe the entire system. Naturally, a question arises as to why not use a single automaton to <em>H</em> to describe the system. Of course we can do this, but this comes with a cost. Take a look at how the automaton <em>H</em> looks like based on our descriptions of <em>H1</em>, <em>H2</em> and <em>H3</em>:</p>
<p><img src="https://iq.opengenus.org/content/images/2024/12/Screenshot-2024-12-02-075859.png" alt="Screenshot-2024-12-02-075859"></p>
<p>This is a complete mess and does not seem human-readable at all. Indeed we must use this hybrid automaton <em>H</em> in the backend when we are, say, mathematically verifying the safety specifications of the system. However, when we are describing the system itself, we are much better off describing the individual components each as a hybrid automaton. This is exactly where CHA comes in.</p>
<p>In this framework, we describe each agent (<em>component</em>) in our system as a hybrid automaton and the entire system can then be studied using the single automaton of the system which we showed above. This automaton is known as the CHA of the system, and is obtained by a mathematical operation known as <strong>composition</strong> (which we denote by the symbol '.'), from where CHA gets its name.</p>
<h2 id="sohowdoicomposehybridautomata">So how do I compose hybrid automata?</h2>
<p>Of course, talking about the composition of the three hybrid automata into a single CHA seems daunting, but don't worry! The '.' operation is commutative as well as associative, which means that we can start with any two components of our choice and go on composing recursively, always ending up with the same final CHA! How does this help? Well, let us consider the tank and the thermometer first. Once we understand how to compose <em>H1</em> and <em>H3</em> to get <em>(H1.H3)</em>, we can simply compose <em>H2</em> and <em>(H1.H3)</em> to get <em>H = H1.H2.H3 = H2.(H1.H3)</em> without any ambiguity.</p>
<p>This is where the fun begins. At the heart of automata composition is a graph operation known as the product of two graphs. Generally speaking, <strong>graph products</strong> are binary operations on graphs which input two graphs to create a new graph. The vertex set of the new graph is the Cartesian product of the vertex sets of the input graphs, while the edge set is constructed via some rule. We are particularly interested in <strong>strong products</strong>. We'll talk about them in a bit. Before that, let us revisit the concept of Cartesian product of two sets. Given two sets, their Cartesian product is defined as all possible ordered pairs that can be formed by selecting one element from the first set and another element from the second.</p>
<p>A classic example of Cartesian products is the standard deck of 52 cards. The ranks {A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2} form a 13-element set. The card suits {♠, ♥, ♦, ♣} form a four-element set. Ranks × Suits returns a set of the form {(A, ♠), (A, ♥), (A, ♦), (A, ♣), (K, ♠), ..., (3, ♣), (2, ♠), (2, ♥), (2, ♦), (2, ♣)}. Suits × Ranks returns a set of the form {(♠, A), (♠, K), (♠, Q), (♠, J), (♠, 10), ..., (♣, 6), (♣, 5), (♣, 4), (♣, 3), (♣, 2)}. Since the order of elements in the pair are irrelevant in our case, these two products are bijective (that is, can be treated as one and the same), and can be expressed as {{A, ♠}, {A, ♥}, {A, ♦}, {A, ♣}, {K, ♠}, ..., {3, ♣}, {2, ♠}, {2, ♥}, {2, ♦}, {2, ♣}}.</p>
<p>Similarly, let us consider two directed graphs as follows:</p>
<p><img src="https://iq.opengenus.org/content/images/2024/12/Screenshot-2024-12-02-145805.png" alt="Screenshot-2024-12-02-145805"></p>
<p>The vertex sets of the two graphs are given as {1, 2, 3, 4} and {5}. The Cartesian product of the two sets is given as {{1, 5}, {2, 5}, {3, 5}, {4, 5}}. This is the vertex set of the graph product. For strong products, an edge exists between vertices {u, u'} and {v, v'} if and only if either of the following conditions are met:</p>
<ul>
<li>u = v and u' is adjacent to v', or</li>
<li>u' = v' and u is adjacent to v, or</li>
<li>u is adjacent to v and u' is adjacent to v'.</li>
</ul>
<p>Following these rules, the strong product for the given two graphs will look like this:</p>
<p><img src="https://iq.opengenus.org/content/images/2024/12/Screenshot-2024-12-02-145939.png" alt="Screenshot-2024-12-02-145939"></p>
<p><strong>Note.</strong> There are several other kinds of graph products based on what rule is being used to construct the edge set. One such product is the <strong>lexicographic product</strong>, which confusingly enough is also called <strong>graph composition</strong>. Don't get confused though; strong products are but a special case of graph composition - all strong products are graph compositions but all graph compositions are not strong products.</p>
<p>Let us now return to the subject of hybrid automata composition. In our discussion of strong products, we talked about taking the Cartesian product of the two graphs as the vertex set of the new graph. But in case of hybrid automata, it's not just about the graph structure anymore. Each location in an automaton also has its own <em>flow</em> and <em>invariant</em>. Aptly then, the flow/invariant of the product location is given as one where the flow/invariant of both the constituent locations hold.</p>
<p>Similarly, each transition has a guard and an assignment. In cases where one location in the pair is fixed and the other is undergoing the transition, the guard/assignment of the transition in the CHA is same as the guard/assignment of the corresponding transition in the input automaton. In cases where both the locations are undergoing a transition, the guard/assignment of the product transition is given as one where the guard/assignment of both the constituent transitions hold.</p>
<p>In case of the <em>inits</em>, the init of the CHA is similarly given as one where the inits of both the components hold. The initial location {<em>u1</em>, <em>u2</em>, ..., <em>uk</em>} for the CHA <em>H1.H2...Hk</em> is chosen such that <em>u1</em> is the initial location of <em>H1</em>, <em>u2</em> is the initial location of <em>H2</em> and so on.</p>
<p>As an example, let us finally take a look at the composition <em>H1.H3</em>, which we are now well-equipped to understand:</p>
<p><img src="https://iq.opengenus.org/content/images/2024/12/Screenshot-2024-12-02-161302.png" alt="Screenshot-2024-12-02-161302"></p>
<p>Similarly, the chaotic mess that is <em>H = H1.H2.H3</em> should hopefully make a bit more sense to you now.</p>
<blockquote>
<p>Why do you think it seems reasonable to use strong products for the composition of hybrid automata?<br>
(Hint: Think about the simulation of a two-agent CPS. Each agent is moving autonomously in the system following their hybrid automaton. At any point in time, the state of the CHA can be given by looking at the states of the components simultaneously.)</p>
</blockquote>
<h2 id="umwheresthecode">Um... where's the code?</h2>
<p>CHA is not a easy affair. Different authors define it in a slightly different manner. The fringe cases are particularly heavily debated. For example, HyST (Hybrid Source Transformer/Translation) is a tool developed by Bak et al. that provides a framework for working with hybrid automata, including a <em>flatten</em> transformation pass for automata composition. While HyST allows composition in cases where inits, invariants or guards are unsatisfiable, it does not in cases where flows or assignments are unsatisfiable.</p>
<p>In the previous article, we already talked about the Verse library and how it makes the modelling of CPS accessible. Verse is extremely capable when it comes to multi-agent systems, but it also ships with certain limitations - such as all agents requiring the same state, and lack of support for shared variables. As such, implementing the tank-burner-thermometer system in Verse is complicated to the point of near-impossibility. However, the model editor tool of SpaceEx provides a GUI interface for this and is suited for modelling this system.</p>
<p>In the upcoming article, we discuss about robot swarms as multi-agent CPS. Verse proves its mettle such scenarios, and therein we discuss in detail how to implement a swarm of robots in Verse.</p>
<p><strong>Note.</strong> It is important to distinguish between homogeneous multi-agent CPS and heterogeneous multi-agent CPS in this context. <strong>Homogeneous multi-agent CPS</strong> consists of agents of the same type, characterized by a single component hybrid automaton (with the same underlying structure) - for example, a swarm of robots. <strong>Heterogeneous multi-agent CPS</strong>, on the other hand, consists of agents of different types, characterized by several different component hybrid automata in the system - as was the case in our tank-burner-thermometer CPS.</p>
<h2 id="conclusion">Conclusion</h2>
<p>To sum up, in this article at OpenGenus, you learnt:</p>
<ul>
<li>what a multi-agent CPS is,</li>
<li>how we model multi-agent CPS using compositional hybrid automata (CHA),</li>
<li>how we compose several components into a single CHA, and</li>
<li>challenges of modelling heterogeneous multi-agent CPS in Verse and how SpaceEx excels in this.</li>
</ul>
<p>In the future, we will explore homogeneous multi-agent CPS in greater detail.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Introduction to Concurrency in Go]]></title><description><![CDATA[A goroutine is a function that runs concurrently to other functions. Channels provide a medium for goroutines to communicate with each other.]]></description><link>https://iq.opengenus.org/concurrency-in-go-once-again/</link><guid isPermaLink="false">65dde67b46912a04ce6cf752</guid><category><![CDATA[Go Programming Language]]></category><dc:creator><![CDATA[Hamza Mateen]]></dc:creator><pubDate>Wed, 27 Nov 2024 15:14:28 GMT</pubDate><media:content url="https://iq.opengenus.org/content/images/2024/08/cold--smooth---tasty..png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><h1 id="tableofcontents">Table of Contents</h1>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#gos-concurrency-model">Go's Concurrency Model</a>
<ul>
<li><a href="#goroutines">Goroutines</a></li>
<li><a href="#channels">Channels</a>
<ul>
<li><a href="#communication-types">Communication Types</a></li>
<li><a href="#buffered-vs-unbuffered-channels">Buffered vs. Unbuffered Channels</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#a-nice-concurrency-problem">A Nice Concurrency Problem</a></li>
</ul>
<h3 id="introduction">Introduction</h3>
<img src="https://iq.opengenus.org/content/images/2024/08/cold--smooth---tasty..png" alt="Introduction to Concurrency in Go"><p><strong>Rob Pike</strong>, one of the creators of the Go programming language, is often attributed with the following quote:</p>
<blockquote>
<p>Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once.</p>
</blockquote>
<p>Simplest real life example to this could arguably be multi-tasking. When we multi-task, we are basically switching from one <strong>task</strong> to another in, hopefully, an efficient manner. That's how we get <em>multiple</em> tasks done in lesser time. That's concurrency for you!</p>
<p>Now imagine you have got a few friends to help <strong>you</strong> through those tasks. Each of you assign yourself to a specific task and then begin the grind. Some time later, every <strong>friend</strong> including <em>you</em> finishes their respective task. This is an example of parallelism.</p>
<p>There exist programming analogues of the few terms that I have emphasized above, these are:</p>
<p><strong>Task</strong>: Any job that is supposed to be performed by a computer program.<br>
<strong>You</strong> : Signifies the <em>main thread</em> of the program which is performing the said task.<br>
<strong>Friend</strong> : This is the <em>helper thread</em> that helps the main thread in getting the task done quickly.</p>
<p>With that out of the way, we can now talk about how Go deals with concurrency.</p>
<h1 id="gosconcurrencymodel">Go's Concurrency Model</h1>
<p>Go introduced a few <strong>constructs</strong> to make it easy for the developers to create concurrently executable programs, namely:</p>
<ol>
<li>Goroutines (co-routines in other languages)</li>
<li>Channels</li>
</ol>
<h2 id="goroutines">Goroutines</h2>
<p>Go uses functions to facilitate the use of goroutines.</p>
<blockquote>
<p>A <em>goroutine</em> is a function that runs concurrently to other functions.</p>
</blockquote>
<p>It is functionally synonymous to an operating system thread because it is an independent unit of execution but there exist several differences, which make goroutines a better choice in terms of concurrency.</p>
<p>For instance, <em>goroutines</em>:</p>
<ul>
<li>are lightweight</li>
<li>have minimal memory-footprint.</li>
<li>are easy to create and manage (via channels).</li>
<li>are scheduled in user-space by the Go scheduler instead of kernel-space by OS kernel.</li>
<li>have low context-switching cost.</li>
</ul>
<p>In Go, if <em>function call</em> is preceded by the keyword <strong>go</strong>, it becomes a goroutine. In code, it looks like this:</p>
<pre><code class="language-Go">package main

func square(num int) {
    return num * num
}

func main() {
    go square(2); 
}
</code></pre>
<p>In Go, every function <em>qualifies</em> to be a goroutine, which implies that a program's <em>main</em> function can also be a goroutine.</p>
<p>In above code snippet, there are two goroutines; <em>main</em> and the <em>greetGuest</em>, former is made into a goroutine by <em>Go runtime</em> whereas <em>greetGuest</em> becomes a goroutine as its invocation follows the <strong>go</strong> keyword.<br>
In this way, the <em>greetGuest</em> function runs concurrently with the <em>main</em> function, and executes its instructions independently.</p>
<p>The <em>main</em> function after creating the goroutine, immediately ends because there are no more instructions to run. It does not wait for the <em>greetGuest</em> goroutine to finish its job. We can change this behaviour, and make it wait but we will look into this later in the article.</p>
<p>As you might have noticed, we didn't store the squared value returned by the square goroutine. This is because we cannot!  Goroutines are not ordinary functions; they are mini-programs that perform specialized tasks which they are created for.</p>
<p>But - what if we absolutely need a goroutine to return a value before terminating? For example, let's say we want to compute the arithmetic sum of an array by decomposing it into subarrays and then process each one using a goroutine? Logically, those goroutines would've to send the computed values back to the <em>main</em> goroutine; this is where <strong>channels</strong> come into play. Channels are the <strong>construct</strong> introduced by Go to manage and synchronize goroutines effectively.</p>
<h2 id="channels">Channels</h2>
<blockquote>
<p>Channels provide a medium for goroutines to communicate with each other.</p>
</blockquote>
<p>They can be used to synchronize the execution and state across goroutines. A channel can be created with its name followed by the keyword <strong>chan <type></type></strong> where <em>type</em> is any built-in data-type.<br>
Channels are shared-memory blocks under the hood. When a channel is created, it is basically a pointer to that memory block which we can share around with goroutines for mutual access.</p>
<pre><code class="language-Go">var ch chan int
</code></pre>
<p>Here, <code>ch</code> is a <code>nil</code> channel of type <code>int</code> which can neither store nor transmit any value because it is not initialized. We can pass it to the built-in <code>make</code> function, which allocates and initializes an object of various types including channel.</p>
<pre><code class="language-Go">ch := make(chan int)
</code></pre>
<p>This is now a proper channel which can help share data among goroutines.</p>
<h3 id="communicationtypes">Communication Types</h3>
<p>Channels facilitate communication between goroutines but communication has several types, such as:</p>
<pre><code>1. Simplex communication
2. Half-duplex communication
3. Full-duplex communication
</code></pre>
<p><strong>Simplex</strong> communication is a unidirectional or a one-way communication scheme where only one side can send data. The receiving side cannot send any information back to the transmitting side. <strong>Publisher-Subscriber</strong> design pattern is based on simplex communication because data flows only from <em>publisher</em> to the <em>subscriber</em> and not the other way around.</p>
<p><strong>Half-duplex</strong> communication occurs when both parties are capable of receiving and transmitting data but only one side can send data at a time. It is sort of a <strong>synchronous</strong> form of communication in the sense that it requires co-ordination from both sides because the data must be consumed by a side before the channel is ready to receive further data.</p>
<p><strong>Full-duplex</strong> is a <strong>synchronous</strong>, two-way communication system where both sides can send and receive data simultaneously. Examples include chat messaging systems, and real-time video-conferencing.</p>
<p>Go enables these communication mechanisms through <strong>Buffered</strong> and <strong>Unbuffered</strong> channels in addition to multi-channel communication.</p>
<h3 id="bufferedvsunbufferedchannels">Buffered vs. Unbuffered Channels</h3>
<p>An <strong>unbuffered</strong> channel can be created using the <code>make</code> function without specifying a buffer size. The<br>
<code>make</code> function, by default, creates a channel of unit capacity, which means that it can hold only one value at a time. Both sides can send and receive data from such a channel but only when the channel is empty. If it's not then the value must first be consumed by either the sender or receiver goroutine. Unbuffered channels help us establish partially <strong>synchronous</strong> communication system between goroutines.</p>
<p>To create a <strong>buffered</strong> channel to establish <strong>asynchronous</strong> communication between goroutines, a <em>buffer size</em> can be passed to the <code>make</code> function along with the channel type. For example:</p>
<pre><code class="language-Go">ch := make(chan int, 2)
</code></pre>
<p>This creates a buffered channel with capacity of holding 2 integer values simulataneously, so the sender, after sending a value to the channel, doesn't have to wait for the receiver to read it, before sending another one.</p>
<p>This communication mode is asynchronous, however, it's not a <strong>Full-duplex</strong> communication system. That could only be achieved if we opened two separate channels instead of increasing the channel capacity. Full-duplex communication requires both parties to be able to send and receive messages at the <strong>same</strong> time, which a single channel cannot allow because concurrent access without blocking can introduce data races.</p>
<p>Let's work through an example to understand the usage and power of <strong>Channels</strong></p>
<h2 id="aniceconcurrencyproblem">A Nice Concurrency Problem</h2>
<blockquote>
<p>Calculate the sum of subarrays concurrently!</p>
</blockquote>
<p>First, create a function that receives a channel and an array to sum.</p>
<p>We initalize the <code>sum</code> variable, then use a <code>for</code> loop to compute the sum of array. Lastly, the computed value is written into the channel with special syntax that is <code>&lt;-</code> (an arrow) <strong>after</strong> the channel name.</p>
<pre><code class="language-Go">func sumSubarray(ch chan int, subarr []int) {
	// initialize the sum variable
	sum := 0

	// compute the sum
	for i := 0; i &lt; len(subarr); i++ {
		sum += subarr[i]
	}

	// write the sum into channel
	ch &lt;- sum
}
</code></pre>
<p>Next, we initialize a channel and a supposedly large integer array, inside the main function. We also calculate the mid-point of array to split it in two equal parts in order to distribute it between a couple of goroutines.</p>
<pre><code class="language-Go">func main() {
	// communication channel
	ch := make(chan int)

	// supposedly large array of integers
	arr := [19]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}

	// calculate the mid-point for splitting
	mid := int(len(arr) / 2)
}
</code></pre>
<p>Now, a <code>totalSum</code> variable is initialized to <code>0</code> to hold the combined sum from different goroutines. Then, a couple of goroutines are created to sum the array segments. We pass the channel <code>ch</code> created above, and the intended segments to each goroutine.</p>
<p>When the first goroutine is created, the main function doesn't wait for the result and continues its execution. It then creates another goroutine to calculate the sum of 2nd half. Array splitting is done through <code>slicing</code> which follows the syntax: <code>arr[start:end]</code>, where the starting index is inclusive while the ending index is exclusive. When the 'end' is omitted, it means to slice through <em>till the end of array</em>.</p>
<pre><code class="language-Go">func main() {
    // ...
    // ...
 
	totalSum := 0

	// create goroutines to
	go sumSubarray(ch, arr[0:mid])
	go sumSubarray(ch, arr[mid:])
}
</code></pre>
<p>Finally, we are ready to receive the partial sums from those goroutines.</p>
<pre><code class="language-Go">func main() {
    // ..
    // ..

	// collect the results
	totalSum += &lt;-ch
	totalSum += &lt;-ch

	// print the results
	fmt.Println(&quot;Total sum: &quot;, totalSum)
}
</code></pre>
<p>To receive from a channel, an arrow <strong>before</strong> its name is placed. We receive a value from the channel, and add it to the <code>totalSum</code> variable. This is a <strong>blocking</strong> operation because we are reading from an empty channel. Execution of the main function would be blocked until one of the goroutines produces a result and sends it to the channel. When it happens, the main function immediately reads it, and adds it to the variable, making the channel empty again. The next instruction would also be a blocking one. We wait until the final goroutine returns a value into the channel which gets added to the total sum.</p>
<p>Finally, the <code>totalSum</code> is printed to the console.</p>
<p>Here's all the code for reference:</p>
<pre><code class="language-Go">package main

import &quot;fmt&quot;

func sumSubarray(ch chan int, subarr []int) {
	// initialize the sum variable
	sum := 0

	// compute the sum
	for i := 0; i &lt; len(subarr); i++ {
		sum += subarr[i]
	}

	// write the sum into channel
	ch &lt;- sum
}

func main() {
	// communication channel
	ch := make(chan int)

	// supposedly large array of integers
	arr := [19]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}

	// calculate the mid-point for splitting
	mid := int(len(arr) / 2)

	totalSum := 0

	// create goroutines to
	go sumSubarray(ch, arr[0:mid])
	go sumSubarray(ch, arr[mid:])

	// collect the results
	totalSum += &lt;-ch
	totalSum += &lt;-ch

	// print the results
	fmt.Println(&quot;Total sum: &quot;, totalSum)
}
</code></pre>
<h2 id="takeaways">Takeaways</h2>
<p>Concurrency in Go makes handling multiple tasks simple, with <em>goroutines</em> and <em>channels</em>. Goroutines let you run functions concurrently in a memory-efficient way, while channels help with friction-less, controlled communication between these goroutines.</p>
<p>Moreover, slicing and channel synchronization, solves problems involving multiple tasks—like splitting and summing arrays. The Go runtime manages much of this behind the scenes.</p>
<blockquote>
<p>I hope you picked up a thing or two from this one, happy learning!!</p>
</blockquote>
</div>]]></content:encoded></item><item><title><![CDATA[Understanding the differences and use Cases of torch.Tensor.max and torch.max in PyTorch]]></title><description><![CDATA[torch.Tensor.max is an instance method that applies directly to a torch.Tensor object and is mainly used to find maximum values within a single tensor. torch.max is a module-level function used to compare two tensors element-wise.]]></description><link>https://iq.opengenus.org/torch-tensor-max-and-torch-max-in-pytorch/</link><guid isPermaLink="false">672c0cf060f05005db557b71</guid><category><![CDATA[PyTorch]]></category><category><![CDATA[Python]]></category><category><![CDATA[Deep Learning]]></category><dc:creator><![CDATA[Godwin AMEGAH]]></dc:creator><pubDate>Thu, 21 Nov 2024 19:01:52 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p><strong>PyTorch</strong> is one of the most popular Deep Learning (DL) libraries today, thanks to its flexibility and ease of use. However, the extensive range of its features can sometimes lead to confusion, especially when two functions appear to have overlapping purposes. This is the case with torch.Tensor.max and torch.max, two methods that allow users to find maximum values in tensors. So, why does <strong>PyTorch</strong> provide two different ways for a similar operation? This article aims to clarify their differences, explore their use cases, and help you make an informed choice.</p>
<h2 id="whytwofunctionsformaximum">Why Two Functions for Maximum?</h2>
<p>PyTorch offers two ways to find maximum values in a tensor because they address different needs:</p>
<ul>
<li>torch.Tensor.max is an instance method that applies directly to a torch.Tensor object and is mainly used to find maximum values within a single tensor.</li>
<li>torch.max is a module-level function used to compare two tensors element-wise.</li>
</ul>
<p>These two functions, therefore, offer specific possibilities that cater to different scenarios. Let’s examine each in detail.</p>
<h3 id="1understandingtorchtensormax">1. Understanding <code>torch.Tensor.max</code></h3>
<h4 id="descriptionandsyntax">Description and Syntax</h4>
<p><code>torch.Tensor.max</code> is an instance method that applies directly to a torch.Tensor object. Its syntax is as follows:</p>
<pre><code class="language-python">tensor.max(dim=None, keepdim=False)
</code></pre>
<ul>
<li><code>dim (int, optional)</code>: The dimension along which to find the maximum value. If no dimension is specified, the method returns the maximum value across the entire tensor.</li>
<li><code>keepdim (bool, optional)</code>: If True, retains the original dimension in the output tensor. This is useful for keeping the tensor structure intact.</li>
</ul>
<h4 id="usecasesoftorchtensormax">Use Cases of torch.Tensor.max</h4>
<p>This method is ideal when you want to:</p>
<ol>
<li>Find the overall maximum value in a tensor.</li>
<li>Obtain both the maximum value and its index along a specific dimension.</li>
</ol>
<h4 id="example">Example</h4>
<p>Consider a 2D tensor:</p>
<pre><code class="language-python">import torch

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

# Find the maximum across the entire tensor
max_value = tensor.max()
print(f&quot;Maximum value in the entire tensor: {max_value}&quot;)

# Find the maximum value along each row
max_values, indices = tensor.max(dim=1)
print(f&quot;Maximum values by row: {max_values}&quot;)
print(f&quot;Indices of maximum values: {indices}&quot;)
</code></pre>
<p>Output:</p>
<pre><code class="language-bash">Maximum value in the entire tensor: 6
Maximum values by row: tensor([5, 6])
Indices of maximum values: tensor([1, 2])
</code></pre>
<p>In this example, we find the global maximum (6) and also the maximum values by row by specifying <strong>dim=1</strong>.</p>
<h3 id="2exploringtorchmax">2. Exploring <code>torch.max</code></h3>
<h4 id="descriptionandsyntax">Description and Syntax</h4>
<p><code>torch.max</code> is a module-level function that compares two tensors element-wise, returning a new tensor containing the maximum values at each position. The syntax is:</p>
<pre><code class="language-python">torch.max(input, other)
</code></pre>
<ul>
<li><code>input</code>: The first tensor.</li>
<li><code>other</code>: The second tensor (must have the same shape as the first).</li>
</ul>
<p>Output:</p>
<pre><code class="language-bash">Tensor with maximum values at each position:
tensor([[2, 5, 4],
        [2, 5, 6]])
</code></pre>
<h3 id="3comparingthetwomethods">3. Comparing the Two Methods</h3>
<h4 id="whentousetorchtensormax">When to Use <code>torch.Tensor.max</code>?</h4>
<pre><code>If you need to extract the maximum value within a single tensor, whether across the entire tensor or along a specific dimension.
When you need to retrieve the index of the maximum value along a specified dimension.
</code></pre>
<h4 id="whentousetorchmax">When to Use <code>torch.max</code>?</h4>
<p>If you want to perform an element-wise comparison between two tensors and retain the maximum value for each position.<br>
Ideal for cases like merging tensors from two sources while keeping the highest values at each position.</p>
<h4 id="performanceandcodereadability">Performance and Code Readability</h4>
<p>Choosing the appropriate method is important not only for optimization but also for code readability. Using torch.Tensor.max for a two-tensor comparison would require additional steps and make the code more complex.</p>
<h2 id="conclusion">Conclusion</h2>
<p>In summary of this OpenGenus article, PyTorch offers both torch.Tensor.max and torch.max to meet specific needs. torch.Tensor.max is your choice for operations within a single tensor, while torch.max is ideal for element-wise comparisons between two tensors. These distinctions, though subtle, are essential for writing efficient and clear code.</p>
</div>]]></content:encoded></item><item><title><![CDATA[An Introduction to Cyber-Physical Systems]]></title><description><![CDATA[Put in simple terms, a cyber-physical system (CPS), as the name suggests, is a dynamical system that exhibits both discrete (cyber) and continuous (physical) dynamic behavior.]]></description><link>https://iq.opengenus.org/introduction-to-cyber-physical-systems/</link><guid isPermaLink="false">673376c662d587044a873e62</guid><dc:creator><![CDATA[Sarthak Das]]></dc:creator><pubDate>Thu, 21 Nov 2024 18:32:25 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><h2 id="introduction">Introduction</h2>
<p>Put in simple terms, a <strong>cyber-physical system (CPS)</strong>, as the name suggests, is a dynamical system that exhibits both discrete (<em>cyber</em>) and continuous (<em>physical</em>) dynamic behavior. Due to their distinct mixed discrete-continuous dynamics, they are also known as <strong>hybrid systems</strong>.</p>
<p>We model such systems using mathematical structures aptly named <strong>hybrid automata.</strong> Let us now look into these structures to get a deeper understanding of what a CPS is.</p>
<h2 id="whatexactlyisahybridautomaton">What exactly is a hybrid automaton?</h2>
<p>Consider as an example of CPS a bouncing ball. Any object under the influence of gravity will certainly act according to the laws of Newtonian mechanics, which are given by ordinary differential equations (ODE). If the ball in question has a height <em>x</em> and a velocity <em>v</em>, and we assume the acceleration due to gravity to be <em>g</em>, we can then come up with a set of ODEs for the ball's physics:</p>
<ul>
<li><em>x</em>' = <em>v</em></li>
<li><em>v'</em> = -<em>g</em></li>
</ul>
<p>One more thing to keep in mind is that the value of <em>x</em> can never be negative, because a negative height does not make sense. This condition is always true, and is known as the <em>invariant</em> of the continuous state defined by the aforementioned flow.</p>
<p>Nothing too fancy, right? Let us name this state as <em>B1</em>. This set of ODEs is then known as the <em>flow</em> of the state, which is sufficient to describe the continuous dynamics of the state. The set of all such states (<em>locations</em>) together with their flow defines the continuous dynamics of the system. In our case, there is only one location.</p>
<p><strong>Note.</strong> The nature of flow in a hybrid automaton is often used to classify hybrid automata into different classes. The example we are dealing with has a set of linear ODEs as its flow, hence is known as a <strong>linear hybrid automaton (LHA)</strong>. If the flows are given by a set of affine ODEs, we call it an <strong>affine hybrid automaton (AHA)</strong>, or more generally, a <strong>nonlinear hybrid automaton (NHA)</strong>.</p>
<p>Now, consider the case when the ball hits the ground. Obviously, the ball will bounce back with a reduced velocity based on some dampening coefficient, which we denote by <em>c</em>. This <em>c</em> depends upon several factors such as the hardness of the surface, the air resistance, and so on, but let us not get into that mess.</p>
<p>In other words, when <em>x</em> reaches 0 value and velocity is in the downward direction, then the ball bounces back with a reduced velocity <em>cv</em> in the opposite direction. Mathematically, we express this as</p>
<ul>
<li>When <em>x</em> &lt;= 0 &amp;&amp; <em>v</em> &lt; 0, then set <em>v</em> to -<em>cv</em> (where 0 &lt; <em>c</em> &lt; 1).</li>
</ul>
<p>Let us call this discrete event as <em>rebound</em>. This is an example of a <em>jump</em>, which checks for a <em>guard condition</em> (<em>x</em> &lt;= 0 &amp;&amp; <em>v</em> &lt; 0) which, when met, triggers an <em>assignment</em>, namely setting <em>v</em> to -<em>cv</em>. The set of all such jumps together defines the discrete dynamics of the system. In our case, there is only one jump.</p>
<p><strong>Note.</strong> We define the guard condition as <em>x</em> &lt;= 0 instead of <em>x</em> == 0. This is because computers can't really handle continuous dynamics, and any ODE computation must be done in very tiny discrete steps, creating an approximation of continuity. As such errors may often creep up, resulting in <em>x</em> jumping from a very negligible positive value to a very negligible negative value instead of actually hitting zero.</p>
<p>All of this looks too verbose. So we must find some way to represent all of this more compactly. This is exactly where the hybrid automata comes in. One can think of hybrid automata as a finite state automata with each state having its own set of ODEs to describe different continuous dynamics that the system can attain, while the state transitions describe the discrete dynamics in the system.</p>
<p>Consider the following diagram:</p>
<p><img src="https://iq.opengenus.org/content/images/2024/11/Screenshot-2024-11-12-223237.png" alt="Screenshot-2024-11-12-223237"></p>
<p>This diagram represents every information we just covered, while noting that the ball was dropped from a height <em>h</em> without applying any additional force (free fall under gravity). This is known as the <em>init</em> or initial condition. We also observe that the execution of the automaton begins at <em>B1</em>, which is our <em>initial location</em>.</p>
<p>Of course, this is a very simplistic example with a single location <em>B1</em> and only two variables. In real world, we often deal with complex CPS which may contain tens of locations and hundreds of variables.</p>
<p><strong>Note.</strong> At <em>x</em> = 0, both the invariant of <em>B1</em> and the guard of the transition <em>Rebound</em> is satisfied. As such, the automaton has a choice to either dwell in the location B1 until the invariant is no longer satisfied, or take the transition. This introduces <em>nondeterminism</em> in the system, but we won't be getting into that today.</p>
<h2 id="okayigetitnowgivemesomecode">Okay, I get it. Now give me some code!</h2>
<p>I'm glad you asked. Let us code this simple bouncing ball example in Python. We will use networkx for implementing the discrete structure and store the continuous dynamics as a set of strings.</p>
<pre><code>import networkx as nx

''' Must use digraphs to model the discrete structure
because having a transition A -&gt; B does not mean
we also have the transition B -&gt; A '''

G = nx.DiGraph()
G.add_node('B1')
G.add_edge('B1','B1',label=&quot;Rebound&quot;)

''' Now let us add the dynamics as meta-data.
Let c be 0.7 and g be the usual 9.8. '''

loc_dict = {} # Stores flow and invariant for each location
flow = [&quot;x'=v&quot;, &quot;v'=-9.8&quot;]
inv = &quot;x&gt;=0&quot;
loc_dict['B1'] = (flow, inv)

trans_dict = {} # Stores guard and assignment for each transition
guard = &quot;x&lt;=0 &amp;&amp; v&lt;0&quot;
asgn = &quot;v=-0.7*v&quot;
trans_dict[&quot;Rebound&quot;] = (guard, asgn)

''' Let us add the initial conditions, assume h = 10'''
init = [&quot;x=10&quot;, &quot;v=0&quot;, 'B1']
</code></pre>
<p>In order to execute (<em>simulate</em>) the hybrid automaton in question, we must have some mechanism to parse these expressions and pass them to some ODE solver, which will solve these and give solutions. All that and we haven't even implemented the invariant anywhere in our code yet. This added complexity makes the entire affair extremely cumbersome.</p>
<h2 id="ahgreatwhatdowedothen">Ah, great. What do we do then?</h2>
<p>Of course one could go about implementing their own hybrid automata library, but several great ones already exist. The industry standard is SpaceEx (not to be confused with Elon Musk's SpaceX) which was developed by the VERIMAG lab of the University of Grenoble.</p>
<p>SpaceEx provides a standardized format to describe hybrid automata as .xml files and implements a tool to parse and execute these files. One can write their own CPS in the easy-to-understand .xml format and run them using SpaceEx. Alternatively, one can also use the SpaceEx model creator, a GUI CPS modelling tool for the more visually inclined.</p>
<p>A more flexible library indeed exists in Python itself called <a href="https://github.com/AutoVerse-ai/Verse-library">Verse</a>, which was developed by the Reliable Autonomy Group at the University of Illinois Urbana-Champaign and funded by NASA. Verse not only makes the modelling of CPS intuitive but also allows users to design custom algorithms for verifying safety properties in such systems. For a taster, here's how one would model the bouncing ball example in Verse.</p>
<p>The continuous dynamics:</p>
<pre><code>from verse.plotter.plotter2D import *
from verse import Scenario, ScenarioConfig
from enum import Enum, auto

class BallAgent(BaseAgent):

    def __init__(self, id, code=None, file_name=None):
        super().__init__(id, code, file_name)

    # Define the flow
    def dynamics(self, t, state):
        x, v = state # Get the continuous variable values at that step
        dxdt = v
        dvdt = -9.8
        return [dxdt, dvdt]
</code></pre>
<p>The discrete dynamics:</p>
<pre><code># Define the continuous and discrete variables
class BallMode(Enum):
    B1 = auto()

class State:
    x = 0.0
    v = 0.0
    mode: BallMode

    def __init__(self, x, v, ball_mode: BallMode):
        pass

# Define the transitions
def decisionLogic(ego: State):
    c = 0.7
    output = copy.deepcopy(ego)
    if ego.x &lt;= 0: # Guard condition
        output.vx = -ego.vx*c # Assignment
        output.x = 0 # Assignment
    assert all(ego.x &gt;= 0), &quot;No negative height&quot; # Invariant
    return output
</code></pre>
<p>And we would simply execute the hybrid automaton as follows:</p>
<pre><code>if __name__ == &quot;__main__&quot;:
        # Initialize a scenario and set the decision logic (discrete dynamics)
        bouncingBall = Scenario(ScenarioConfig(parallel=False))
        myball = BallAgent(&quot;ball&quot;, file_name=&quot;./bouncing_ball.py&quot;)
        bouncingBall.add_agent(myball)
        
        # Set the initial conditions
        bouncingBall.set_init([[[10, 0]], # Lower bound for init x, v
            [[10, 0]], # Upper bound for init x, v
            [(BallMode.B1)]) # Initial location 

        # Simulate for 40 seconds, where ODE computation is done every 0.01 seconds
        traces = bouncingBall.simulate_simple(40, 0.01)
        
        # Print the trajectory (x vs. t graph)
        fig = go.Figure()
        fig = simulation_tree(traces, None, fig, 0, 1, [0, 1], &quot;fill&quot;, &quot;trace&quot;)
        fig.show()
</code></pre>
<p>And that's it! Upon simulation, we would get a trajectory similar to this:</p>
<p><img src="https://iq.opengenus.org/content/images/2024/11/360_F_506127412_DdOCy5t0bdiiNCGZd00O5LFjNg8FCpRO.jpg" alt="360_F_506127412_DdOCy5t0bdiiNCGZd00O5LFjNg8FCpRO"></p>
<blockquote>
<p>Take a moment to ponder on that. Why do you think the trajectory looks like this?</p>
</blockquote>
<p><strong>Note.</strong> Verse's framework is designed for multi-agent CPS (more on that in the future) and offers an alternative way to model CPS than hybrid automata. However, the framework is designed in such a way that every agent in Verse (such as our ball agent) will have an equivalent hybrid automaton, and vice versa. As such, Verse can be effectively used to model, simulate and verify any given hybrid automaton.</p>
<h2 id="butwhatisitgoodfor">But what is it good for?</h2>
<p>Excellent question! CPS are found everywhere - in highly autonomous vehicles (think Tesla's self-driving cars and NASA's unmanned satellites), robotics and telecommunication networks, distributed realtime systems, distributed artificial intelligence, surveillance systems, industrial control systems, power systems and smartgrids, coordinated defence systems, and healthcare.</p>
<p>In fact, most of these use cases are often safety-critical, where ensuring the operational correctness is absolutely necessary. Consider, for example, autonomous vehicles, insulin infusion pumps, and so on. Therefore, the formal verification of these system becomes a critical area of study in theoretical computer science and control theory.</p>
<h2 id="conclusion">Conclusion</h2>
<p>To sum up, in this article at OpenGenus, you learnt:</p>
<ul>
<li>what a cyber-physical system (CPS) is,</li>
<li>how we model CPS using hybrid automata,</li>
<li>how to code your own hybrid automata in Python, and</li>
<li>application domains of CPS.</li>
</ul>
<p>In the future, we will dive deeper by exploring more complex types of CPS.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Understanding Linux Namespaces: The Building Blocks of Containerization]]></title><description><![CDATA[Containerization uses specific features of the Linux kernel to create isolated environments for running applications.]]></description><link>https://iq.opengenus.org/linux-namespaces/</link><guid isPermaLink="false">671a7ae460f05005db557b2c</guid><category><![CDATA[Linux]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Shruti]]></dc:creator><pubDate>Thu, 24 Oct 2024 18:30:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Let me give you a rough idea of containerization metaphoricaly. Imagine living in a house with no rooms, utter chaos and no privacy, where everything blends together. Horrible right!  Now, picture introducing rooms: suddenly, life feels organized and beautiful!(yes privacy too!) Similarly, containerization brings order to software development, creating isolated environments for applications. This way, chaos transforms into efficiency and clarity, making it easier to manage, deploy, and scale applications.</p>
<p>In a general computing environment, processes share the same set of resources, creating potential conflicts and challenges in resource management. In this scenario, processes share a common namespace, leading to a lack of isolation and independence. Resource conflicts, such as two processes trying to access the same memory address or conflicting file access, can result in unstable and unpredictable behavior.</p>
<p>Containerization is essential in modern software development and deployment due to its benefits: isolation, portability, resource efficiency, scalability, faster deployment, enhanced security, and more. In this article, we will explore the core technologies behind popular containerization software like Docker, Kubernetes, and Podman, as well as notable cloud providers.</p>
<h2 id="howdoescontainerizationwork">How does containerization work?</h2>
<p>Containerization uses specific features of the Linux kernel to create isolated environments for running applications. For eg this is what Docker states on their website:-</p>
<blockquote>
<p>Docker uses a technology called namespaces to provide the isolated workspace called the container. When you run a container, Docker creates a set of namespaces for that container.</p>
</blockquote>
<p>Docker employs Linux namespaces, cgroups, and seccomp Linux features, and this is also true for other well-known container technologies. The core concepts and components involved are namespaces, control groups (cgroups), chroot, and union file systems. In this article, we will focus on Linux namespaces.</p>
<h2 id="linuxnamespaceswhatarethey">Linux Namespaces: What are they?</h2>
<p>Linux namespace is a fundamental linux kernel feature that enables the isolation of resources within a system. Currently, Linux implements six different types of namespaces. The purpose of each namespace is to wrap a particular global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource. Here’s what the man pages say about namespaces:</p>
<blockquote>
<p>A namespace wraps a global system resource in an abstraction that<br>
makes it appear to the processes within the namespace that they<br>
have their own isolated instance of the global resource.  Changes<br>
to the global resource are visible to other processes that are<br>
members of the namespace, but are invisible to other processes.<br>
One use of namespaces is to implement containers.</p>
</blockquote>
<p>Linux supports six distinct namespace types. By wrapping a specific global system resource in an abstraction, each namespace aims to provide the impression that the processes running inside it have their own isolated instance of the global resource. Process IDs, file system mount points, network interfaces, IP addresses, routing tables, firewall rules, hostnames, NIS domain names, and so forth are examples of global resources.</p>
<p>Given below is the table from man pages of namespaces showing the types:-<br>
<img src="https://iq.opengenus.org/content/images/2024/10/namespaceTypes.PNG" alt="namespaceTypes"></p>
<h2 id="understandingpidnamespaces">Understanding PID Namespaces</h2>
<p>I will delve further into pid namespaces and provide a basic code output in this post to help readers grasp isolation and gain a clear idea of how namespaces function.<br>
According to the manpages:-</p>
<blockquote>
<p>PID namespaces isolate the process ID number space, meaning that<br>
processes in different PID namespaces can have the same PID.  PID<br>
namespaces allow containers to provide functionality such as<br>
suspending/resuming the set of processes in the container and<br>
migrating the container to a new host while the processes inside<br>
the container maintain the same PIDs.<br>
PIDs in a new PID namespace start at 1, somewhat like a<br>
standalone system, and calls to fork(2), vfork(2), or clone(2)<br>
will produce processes with PIDs that are unique within the<br>
namespace.</p>
</blockquote>
<p>To explain this better I have attached a picture:</p>
<p><img src="https://iq.opengenus.org/content/images/2024/10/pidNamespaces2.jpg" alt="pidNamespaces2"></p>
<p>A Process ID (PID) is a unique numerical identifier assigned by the operating system to each running process. It allows the system to distinguish between different processes, hence manage and track processes effectively. Linux establishes a single init pid_namespace by default, and all processes live inside of it. It is possible for processes to generate a new pid_namespace and assign their child processes to it. The new pid_namespace inherits the parent pid_namespace as a child. In a new pid_namespace, the PID number begins with 1.</p>
<ul>
<li>Processes are assigned unique numbers in the parent (init) namespace.</li>
<li>In a child namespace, processes have PID as 1, 2, 3, while the parent sees them as PID 4, 5, 6.</li>
<li>If a grandchild namespace is created from a process(in fig process ID 1) in the child namespace, processes there will also see their PIDs starting from 1, while the parent namespaces see them as higher-numbered PIDs.</li>
</ul>
<h2 id="experiment">Experiment</h2>
<p>To demonstrate the above concept here is the code in C below. This C program illustrates how to create a new PID namespace and run a child process within that namespace. :-</p>
<pre><code class="language-C">#define _GNU_SOURCE
#include &lt;sched.h&gt;
#include &lt;unistd.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;sys/wait.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;string.h&gt;
#include &lt;signal.h&gt;
#include &lt;stdio.h&gt;

/* A simple error-handling function: print an error message based
   on the value in 'errno' and terminate the calling process */

#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
                        } while (0)

static int              /* Start function for cloned child */
childFunc(void *arg)
{
    printf(&quot;childFunc(): PID  = %ld\n&quot;, (long) getpid());
    printf(&quot;childFunc(): PPID = %ld\n&quot;, (long) getppid());

    char *mount_point = arg;

   printf(&quot;Programme done&quot;);
    execlp(&quot;sleep&quot;, &quot;sleep&quot;, &quot;600&quot;, (char *) NULL);
    errExit(&quot;execlp&quot;);  /* Only reached if execlp() fails */
}

#define STACK_SIZE (1024 * 1024)

static char child_stack[STACK_SIZE];    /* Space for child's stack */

int
main(int argc, char *argv[])
{
    pid_t child_pid;

    printf(&quot;Parent Process: PID  = %ld\n&quot;, (long) getpid());
    printf(&quot;Parent Process: PPID = %ld\n&quot;, (long) getppid());

    child_pid = clone(childFunc,
                    child_stack + STACK_SIZE,   /* Points to start of
                                                   downwardly growing stack */
                    CLONE_NEWPID | SIGCHLD, argv[1]);

    if (child_pid == -1)
        errExit(&quot;clone&quot;);

    printf(&quot;PID returned by clone(): %ld\n&quot;, (long) child_pid);

    if (waitpid(child_pid, NULL, 0) == -1)      /* Wait for child */
        errExit(&quot;waitpid&quot;);

    exit(EXIT_SUCCESS);
}

</code></pre>
<h2 id="codeexplanation">Code explanation</h2>
<p>In the above code,  the childFunc()  is the function executed by the child process created in the new PID namespace. It does following work:-</p>
<ul>
<li>It prints the child’s PID and parent PID (PPID).</li>
<li>It calls execlp to run the sleep command for 600 seconds. This replaces the current process image with the sleep program.</li>
<li>If execlp fails, it calls errExit.</li>
</ul>
<p>The parent process prints its own PID and PPID (main function). The clone function is called to create a new child process in a new PID namespace. The clone()  system call creates a new process in a new PID namespace, taking following parameters:-</p>
<ul>
<li>childFunc: The function to run in the child process.</li>
<li>child_stack + STACK_SIZE: Specifies the top of the stack pointer for the child (since the stack grows downwards). Stack and its size provided above main() function</li>
<li>CLONE_NEWPID: flag to ensure the child gets its own PID namespace.<br>
SIGCHLD: Sends a signal to the parent when the child terminates.</li>
</ul>
<p>If clone() succeeds, it returns the child's PID, which is then printed. The parent process waits for the child to complete using waitpid, ensuring proper cleanup before exiting.</p>
<h3 id="output">Output</h3>
<p>Compiling and running the program in bash gives:-</p>
<p><img src="https://iq.opengenus.org/content/images/2024/10/output-1.PNG" alt="output-1"><br>
<em>(yappye??   Yeah that's me 😁)</em></p>
<p>When the program runs, the parent process PID(process ID) ie 41 and PPID(parent process ID) ie 40 is printed initially in main() function. Next, after the child process is created using the clone function, the child process prints its own PID and PPID. From parent's namespace perspective child process ID appears as 42.<br>
However, within the child namespace, the child process sees its PID as 1 and its PPID as 0.</p>
<p>This output demonstrates how PID namespaces provide isolation by allowing the same process to have distinct PIDs based on the namespace from which it is viewed. In the child namespace, the process ID begins at 1, similar to the behavior of a standalone system, yet the parent process sees it as 42 in its own namespace.</p>
<h3 id="additionalcommandsrun">Additional Commands Run</h3>
<ol>
<li>The ps -ef command is a common way to display information about currently running processes in a Linux system.</li>
</ol>
<pre><code class="language-bash">ps -ef
</code></pre>
<h4 id="output">Output</h4>
<p><img src="https://iq.opengenus.org/content/images/2024/10/psef-1.JPG" alt="psef-1"><br>
When we run ps -ef after executing the &quot;pidns_init_sleep.c&quot; program, you will see a list of all running processes, including the parent and child processes created by the program (shown by arrows).<br>
We can observe in the output that the child process with PID 42 and PPID as 41, showing that it was spawned by the main program(./a.out). It runs the &quot;sleep 600&quot; command for 600 seconds.</p>
<ol start="2">
<li>The pstree -n command provides a visual representation of the process tree on a Linux system, showing the hierarchical relationship between processes.</li>
</ol>
<pre><code class="language-bash">pstree -n
</code></pre>
<h4 id="output">Output</h4>
<p>The output for above command before running the program.<br>
<img src="https://iq.opengenus.org/content/images/2024/10/pstreeBefore.JPG" alt="pstreeBefore"></p>
<p>The output for above command after running the program. We can observe the ./a.out program creating process &quot;sleep&quot;(child process).<br>
<img src="https://iq.opengenus.org/content/images/2024/10/pstree-1.JPG" alt="pstree-1"></p>
<h2 id="conclusion">Conclusion</h2>
<p>To summarize, Linux namespaces, particularly PID namespaces, play an important role in containerization by isolating and independent processes. This allows numerous processes to coexist without interference, with the same PID in various namespaces. In this article we have covered only PID namespaces. In iupcomming article we will discover other namespaces too. Stay tuned!✌</p>
</div>]]></content:encoded></item><item><title><![CDATA[Goals of Network Security]]></title><description><![CDATA[Network security is a critical aspect of modern computer networks, ensuring the protection of data, systems, and resources from unauthorized access, damage, or disruption.]]></description><link>https://iq.opengenus.org/goals-of-network-security/</link><guid isPermaLink="false">670d9c0560f05005db557a0c</guid><category><![CDATA[cyber security]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Kazi Priom]]></dc:creator><pubDate>Wed, 23 Oct 2024 21:08:48 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><h1 id="tableofcontents">Table of Contents</h1>
<ol>
<li><a href="#1-introduction">Introduction</a></li>
<li><a href="#2-confidentiality">Confidentiality</a>
<ul>
<li>Definition</li>
<li>Protocols to Ensure Confidentiality</li>
<li>Attacks on Confidentiality</li>
</ul>
</li>
<li><a href="#3-integrity">Integrity</a>
<ul>
<li>Definition</li>
<li>Protocols to Ensure Integrity</li>
<li>Attacks on Integrity</li>
</ul>
</li>
<li><a href="#4-authentication">Authentication</a>
<ul>
<li>Definition</li>
<li>Protocols to Ensure Authentication</li>
<li>Attacks on Authentication</li>
</ul>
</li>
<li><a href="#5-availability">Availability</a>
<ul>
<li>Definition</li>
<li>Protocols to Ensure Availability</li>
<li>Attacks on Availability</li>
</ul>
</li>
</ol>
<hr>
<h2 id="1introduction">1. Introduction</h2>
<p>Network security is a critical aspect of modern computer networks, ensuring the protection of data, systems, and resources from unauthorized access, damage, or disruption. As the amount of sensitive information transmitted over networks continues to grow, so does the need to safeguard it against various types of threats. The primary goals of network security include <strong>confidentiality</strong>, <strong>integrity</strong>, <strong>authentication</strong>, and <strong>availability</strong>. These goals work together to ensure that only authorized individuals can access data, that data remains unaltered during transmission, that the identities of users and devices can be trusted, and that network services are accessible when needed. To achieve these objectives, a range of protocols and techniques are employed, while simultaneously defending against a variety of attacks aimed at compromising security. Understanding and addressing these goals are essential for creating secure and resilient network infrastructures.</p>
<hr>
<h2 id="2confidentiality">2. Confidentiality</h2>
<p><strong>Definition</strong>: Confidentiality ensures that information is accessible only to those who are authorized to view it. In other words, it prevents unauthorized individuals from accessing sensitive data during transmission or storage.</p>
<p><strong>Protocols to ensure confidentiality</strong>:</p>
<ul>
<li><strong>Encryption</strong> is the primary mechanism to maintain confidentiality. Some widely used encryption algorithms include:
<ul>
<li><strong>Feistel-based encryption</strong>: Block cipher methods like <strong>DES (Data Encryption Standard)</strong> and <strong>3DES</strong> use the Feistel structure to transform plaintext into ciphertext.</li>
<li><strong>AES (Advanced Encryption Standard)</strong>: A modern block cipher widely used for securing sensitive data.</li>
<li><strong>RSA</strong> and <strong>ECC (Elliptic Curve Cryptography)</strong>: Public-key encryption algorithms used for secure communication.</li>
<li><strong>TLS/SSL (Transport Layer Security)</strong>: Ensures encrypted communication over the Internet for applications like web browsing (HTTPS).</li>
</ul>
</li>
</ul>
<p><strong>Attacks on confidentiality</strong>:</p>
<ul>
<li><strong>Brute force attacks</strong>: Attempting to decrypt data by trying all possible keys.</li>
<li><strong>Known plaintext attack (KPA)</strong>: Where the attacker knows both plaintext and ciphertext pairs and uses them to break the encryption.</li>
<li><strong>Chosen ciphertext attack (CCA)</strong>: The attacker can select a ciphertext and obtain its decryption to derive more information.</li>
<li><strong>Meet-in-the-middle attack</strong>: This attack is often used against block ciphers like 3DES, where the attacker tries to find intermediate values to reduce the complexity of decrypting data.</li>
</ul>
<hr>
<h2 id="3integrity">3. Integrity</h2>
<p><strong>Definition</strong>: Integrity ensures that the data being transmitted or stored is not altered or tampered with, either maliciously or accidentally. The goal is to ensure that the data remains consistent and accurate from the sender to the receiver.</p>
<p><strong>Protocols to ensure integrity</strong>:</p>
<ul>
<li><strong>Hash functions</strong>: Algorithms like <strong>SHA-256</strong> and <strong>MD5</strong> generate a fixed-size output from input data. Any change to the input will result in a different hash, signaling tampering.</li>
<li><strong>Checksums</strong>: Used to detect accidental data corruption by comparing the checksum value before and after transmission.</li>
<li><strong>Message Authentication Codes (MAC)</strong>: Ensure both integrity and authenticity by appending a code created from a secret key.</li>
<li><strong>Digital signatures</strong>: Often used in combination with public-key cryptography, these signatures provide a method to verify that a message or document has not been altered.</li>
</ul>
<p><strong>Attacks on integrity</strong>:</p>
<ul>
<li><strong>Man-in-the-middle attack (MITM)</strong>: The attacker intercepts and possibly alters the communication between two parties, leading to compromised integrity.</li>
<li><strong>Replay attacks</strong>: An attacker captures valid data transmissions and replays them later to achieve unauthorized results.</li>
<li><strong>Data modification attack</strong>: An attacker intercepts and modifies data in transit, possibly corrupting files, emails, or even transactions.</li>
</ul>
<hr>
<h2 id="4authentication">4. Authentication</h2>
<p><strong>Definition</strong>: Authentication ensures that the entity involved in communication is who they claim to be. This goal applies to both users and devices, confirming their identity before allowing access to sensitive data or network resources.</p>
<p><strong>Protocols to ensure authentication</strong>:</p>
<ul>
<li><strong>Password-based authentication</strong>: Simple usernames and passwords are the most common form of authentication.</li>
<li><strong>Multi-factor authentication (MFA)</strong>: Combines two or more independent credentials, such as a password, a one-time code, or biometric verification (fingerprint or face recognition).</li>
<li><strong>Kerberos</strong>: A network authentication protocol using secret-key cryptography and tickets to verify users' identities.</li>
<li><strong>Digital certificates</strong>: Issued by <strong>certificate authorities (CAs)</strong>, these are used to verify the identity of devices or websites in protocols like <strong>SSL/TLS</strong>.</li>
</ul>
<p><strong>Attacks on authentication</strong>:</p>
<ul>
<li><strong>Password cracking</strong>: Using tools like brute force or dictionary attacks to guess or compute a user’s password.</li>
<li><strong>Phishing</strong>: An attacker impersonates a trusted entity to trick users into revealing their login credentials.</li>
<li><strong>Session hijacking</strong>: The attacker takes control of a user's session by stealing their session token or cookies.</li>
<li><strong>Credential stuffing</strong>: Using stolen credentials from one service to gain access to other accounts due to password reuse.</li>
</ul>
<hr>
<h2 id="5availability">5. Availability</h2>
<p><strong>Definition</strong>: Availability ensures that network services, systems, and data are accessible to authorized users when needed. It ensures that there is no disruption in service, allowing continuous access to network resources and services.</p>
<p><strong>Protocols to ensure availability</strong>:</p>
<ul>
<li><strong>Redundancy</strong>: Network devices, systems, and servers often have backups to ensure that even if one system fails, others can take over.</li>
<li><strong>Load balancing</strong>: Distributes traffic across multiple servers to ensure no single server is overwhelmed, maintaining service availability.</li>
<li><strong>Firewalls</strong>: Provide defense against unauthorized access and attacks, helping maintain availability by blocking malicious traffic.</li>
<li><strong>DDoS protection</strong>: Mechanisms like <strong>rate limiting</strong> and <strong>cloud-based DDoS mitigation</strong> are used to protect against Distributed Denial of Service (DDoS) attacks, which aim to overwhelm a network with traffic.</li>
</ul>
<p><strong>Attacks on availability</strong>:</p>
<ul>
<li><strong>Denial of Service (DoS)</strong>: An attacker floods the network or service with excessive traffic, making it unavailable to legitimate users.</li>
<li><strong>Distributed Denial of Service (DDoS)</strong>: Similar to DoS, but the attack is launched from multiple compromised systems.</li>
<li><strong>Botnets</strong>: Networks of compromised devices that are used to perform massive-scale DDoS attacks.</li>
<li><strong>Ransomware</strong>: Malware that locks down systems or data, demanding ransom to restore access, affecting the availability of critical services.</li>
</ul>
<hr>
<p>These four goals—<strong>confidentiality</strong>, <strong>integrity</strong>, <strong>authentication</strong>, and <strong>availability</strong>—form the core of network security. Ensuring each of these is protected is vital for safeguarding sensitive data and maintaining the smooth operation of any network. However, each of these security aspects is constantly under threat from evolving and sophisticated attacks. To protect against these, organizations must employ a combination of security protocols, best practices, and proactive defenses, while remaining vigilant in identifying and addressing new vulnerabilities.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Basics of OOP in Java: Contact Book Program]]></title><description><![CDATA[In this OpenGenus article, you will learn how to apply the basic concepts of object-oriented programming (OOP) to develop a simple, console-based contact book application.]]></description><link>https://iq.opengenus.org/oop-in-java-contact-book-program/</link><guid isPermaLink="false">66de07f760f05005db557780</guid><category><![CDATA[Java]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Scott Chen]]></dc:creator><pubDate>Wed, 23 Oct 2024 20:12:51 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><h2 id="tableofcontents">Table of Contents</h2>
<ol>
<li>Prerequisites</li>
<li>Introduction</li>
<li>The Contact class</li>
<li>The ContactBook class</li>
<li>Putting it all together - The ContactBookClient class</li>
<li>Summary</li>
<li>Key Concepts</li>
<li>Conclusion</li>
</ol>
<h2 id="prerequistes">Prerequistes</h2>
<p>This OpenGenus article is intended for those who have knowledge of basic Java syntax such taking input/output from the user using Scanner, data types and variables, loops and conditions, classes and objects, exception handling and ArrayList and are ready to build their first project using object-oriented programming.</p>
<h2 id="tools">Tools</h2>
<p>Installation of JDK 17 or higher and an IDE of your choice.</p>
<h2 id="introduction">Introduction</h2>
<p>In this OpenGenus article, you will learn how to apply the basic concepts of object-oriented programming (OOP) to develop a simple, console-based contact book application. This application will allow users to store, view, edit, and manage a list of contacts efficiently using core OOP principles such as classes, objects, encapsulation, and methods.Your application will be have the following features:</p>
<p><strong>Add a contact</strong>: Users can add a new contact by providing the name, phone number, and email.<br>
<strong>View contacts</strong>: Users can view the list of contacts stored in the Contact Book.<br>
<strong>Edit a contact</strong>: Users can edit the details of an existing contact, including the name, phone number, and email.<br>
<strong>Delete a contact</strong>: Users can delete a contact from the Contact Book.</p>
<p><strong>In this article we will follow the principle of incremental development where I will give you some boilerplate code so that you can implement the code according to the directions. Please try writing the code yourself before looking at my implementation.</strong></p>
<h2 id="thecontactclass">The Contact Class</h2>
<p><strong>Object-oriented programming</strong> (OOP) is a paradigm that uses objects to represent real-world entities and their interactions, helping us design more organized and maintainable applications. For example, consider the contacts list on your iPhone: each contact has attributes like name, email, and phone number. You can also perform actions such as adding, editing, and deleting contacts. We'll use OOP principles to model this relationship in our code. Let's start implementing our <code>Contact</code> class, which represents a single contact or the most basic unit of our contact book.</p>
<h3 id="defininginstancevariables">Defining Instance Variables</h3>
<pre><code class="language-java">public class Contact {
    //define instance variables here
}
</code></pre>
<details close="">
  <summary>Answer</summary>
    <pre><code class="language-java">public class Contact {
        private String name;
        private String phoneNumber;
        private String email;
    }
 </code></pre>
</details>
&nbsp;
<p>In Java, it is best practice to keep instance variables private so that they cannot be modified from other classes.</p>
<h3 id="initializingourcontactobjectwithaconstructor">Initializing our Contact object with a constructor</h3>
<pre><code class="language-java">	public Contact(String name, String phoneNumber, String email) {
		//initialize instance variables here
	}
</code></pre>
<details close="">
  <summary>Answer</summary>
    <pre><code class="language-java">
    public Contact(String name, String phoneNumber, String email) {
		this.name = name;
		this.phoneNumber = phoneNumber;
		this.email = email;
	}
 </code></pre>
</details>
&nbsp;
<p>A constructor in Java is a special method that is called when you create a new object of a class. It initializes the object and sets up its initial state. The keyword this is <strong>a reference to the current object</strong> (the object whose constructor is being called). It's used to distinguish between instance variables and parameters or other variables with the same name.</p>
<p>Key points:</p>
<ul>
<li>It has the same name as the class.</li>
<li>It doesn't have a return type, not even void.</li>
<li>It's used to assign values to the object's variables when the object is created</li>
</ul>
<h2 id="gettersandsetters">Getters and Setters</h2>
<p>Getters and setters in Java help with <strong>encapsulation</strong> by keeping a class's variables private and controlling how they are accessed or changed. Getters let you read the value, while setters allow you to update it safely, ensuring the data stays valid and secure. This keeps the internal details of the class hidden from outside code. Let's add our getters and setters for the <code>Contact</code> class.</p>
<pre><code class="language-java">        public String getPhoneNumber() {
		//your implementation here
	}

	public String getName() {
		//your implementation here
	}

	public String getEmail() {
		//your implementation here
	}

	public void setPhoneNumber(String phoneNumber) {
		//your implementation here
	}

	public void setName(String name) {
		//your implementation here
	}

	public void setEmail(String email) {
		//your implementation here
	}
</code></pre>
<details close="">
  <summary>Answer</summary>
    <pre><code class="language-java">
    public String getPhoneNumber() {
        return this.phoneNumber;
	}
<pre><code>public String getName() {
	return this.name;
}

public String getEmail() {
	return this.email;
}

public void setPhoneNumber(String phoneNumber) {
	this.phoneNumber = phoneNumber;
}

public void setName(String name) {
	this.name = name;
}

public void setEmail(String email) {
	this.email = email;
}
</code></pre>
<p></p></code></pre><p></p>
</details>
&nbsp;
<h2 id="equalsmethod">Equals Method</h2>
<p>We'll use this method to compare whether 2 contacts have the same name, email, and phone number in order to avoid adding duplicate contacts to our contact book.</p>
<pre><code class="language-java">	public boolean equals(Contact contact) {
		//your implementation here
	}
</code></pre>
<details close="">
  <summary>Answer</summary>
    <pre><code class="language-java">
    	public boolean equals(Contact contact) {
		return this.name.equals(contact.email)
				&& this.email.equals(contact.name)
				&& this.phoneNumber.equals(contact.phoneNumber); //use .equals to compare strings 
	}
 </code></pre>
</details>
&nbsp;
<h2 id="tostringmethod">toString() Method</h2>
<p>Java's default <code>toString()</code> method returns a string that represents the object's memory address, which isn't very useful when we want to display meaningful information about an object. By overriding the default <code>toString()</code> method in our class, we can customize how an object is represented as a string. This is important for providing clear and readable output when viewing the details of an object, such as a contact list.</p>
<pre><code class="language-java">public String toString() {
		//your implementation here
	}
</code></pre>
<details close="">
  <summary>Answer</summary>
    <pre><code class="language-java">
    	public String toString() {
		String name = "Contact name: " + this.name + "\n";
		String email = "Contact email: " + this.email + "\n";
		String phoneNumber = "Contact phone number: " + this.phoneNumber + "\n";
		return name + email + phoneNumber;
	}
 </code></pre>
</details>
&nbsp;
<h1 id="thecontactbookclass">The ContactBook class</h1>
<p>Now that we've defined the attributes of the Contact object, we need to implement the methods that will let users view, add, edit, and delete contacts. To manage these operations, we'll create a new class called ContactBook. This class will serve as a collection and manager for our contacts.</p>
<h2 id="arraylistofcontacts">ArrayList of Contacts</h2>
<p>This is where we'll store the contact information. Since an ArrayList can hold objects of any type, we'll initialize it to store Contact objects specifically.</p>
<pre><code class="language-java">public class ContactBook {
   //initialize ArrayList here
}
</code></pre>
<details close="">
  <summary>Answer</summary>
    <pre><code class="language-java">
    	private ArrayList<contact> list = new ArrayList<contact>();
 </contact></contact></code></pre>
</details>
&nbsp;
<p>Again, we want to make our instance variables private to follow the principle of <strong>encapsulation.</strong></p>
<h2 id="viewcontactlist">View contact list</h2>
<p>Prints out all our entries in our contact book along with each corresponding entry number. Hint: Can you use a method from the Contact class to display Contact info?</p>
<pre><code class="language-java">	public void view() {
    		System.out.println(&quot;\nViewing all Contact Book entries&quot;);
		//your implementation here
	}
</code></pre>
<details close="">
  <summary>Answer</summary>
    <pre><code class="language-java">
    public void view() {
		System.out.println("\nViewing all Contact Book entries");
		for (int i = 0; i < list.size(); i++) {
			System.out.println("-----------");
			System.out.println("Entry #" + (i + 1));
			System.out.println(list.get(i).toString());
		}
	}
 </code></pre>
</details>
&nbsp;
<h2 id="addacontact">Add a contact</h2>
<p>Checks if the contact already exists in the contact book. If so, inform the user that they are trying to add a duplicate contact. Otherwise, add an instance of <code>Contact</code> to our contact book. Hint: Can you use a method from the Contact class to check for duplicates?</p>
<pre><code class="language-java">	public void add(String name, String email, String phoneNumber) {
    		Contact contact = new Contact(name, email, phoneNumber);
		//your implementation here
	}
</code></pre>
 <details close="">
  <summary>Answer</summary>
    <pre><code class="language-java">
    public void add(String name, String email, String phoneNumber) {
		Contact contact = new Contact(name, email, phoneNumber);
		for (Contact c : list) {
			if (c.equals(contact)) {
				System.out.println("\nContact with phone number, name, and " + "email already exists in contact book");
				return;
			}
		}
<pre><code>	list.add(contact);
	int entryNum = list.indexOf(contact) + 1;
	System.out.println(&quot;Entry # &quot; + entryNum + &quot; successfully added to contact book!\n&quot;);
}
</code></pre>
<p></p></code></pre><p></p>
</details>
&nbsp;
<p><strong>For editing and deleting contacts we will prompt the user for the entry that they would like to edit or delete in the main method.</strong></p>
<h2 id="editcontact">Edit contact</h2>
<p>Retrives and prints out information about the contact. Prompt the user to change the contact's name, email, and phone number and set them to the new values in our <code>Arraylist</code>.</p>
<pre><code class="language-java">	public void edit(int entry) {
		int index = entry - 1;
		//get the contact from the array list
		
		System.out.println(&quot;\nEntry #&quot; + (entry));
        //print contact information
				
		Scanner s = new Scanner(System.in);
		
		System.out.print(&quot;\nEdit name: &quot;);
        //read user input and set name of contact
		
		System.out.print(&quot;Edit Email: &quot;);
        //read user input and set email of contact
		
		System.out.print(&quot;Edit phone number: &quot;);
        //read user input and set phone number of contact
		
		System.out.println(&quot;\nContact edited successfully!&quot;);
	}
</code></pre>
 <details close="">
  <summary>Answer</summary>
    <pre><code class="language-java">
    	public void edit(int entry) {
		int index = entry - 1;
		Contact contact = list.get(index);
<pre><code>	System.out.println(&quot;\nEntry #&quot; + (entry));
	System.out.println(contact.toString());
	
	Scanner s = new Scanner(System.in);
	
	System.out.print(&quot;\nEdit name: &quot;);
	String name = s.nextLine();
	contact.setName(name);
	
	System.out.print(&quot;Edit Email: &quot;);
	String email = s.nextLine();
	contact.setEmail(email);
	
	System.out.print(&quot;Edit phone number: &quot;);
	String phoneNumber = s.nextLine();
	contact.setPhoneNumber(phoneNumber);
	
	System.out.println(&quot;\nContact edited successfully!&quot;);
}
</code></pre>
<p></p></code></pre><p></p>
</details>
&nbsp;
<h2 id="deletecontact">Delete contact</h2>
<p>Removes the entry from the <code>ArrayList</code>. Hint: Java ArrayList's use 0 based indexing, meaning that the first element in the ArrayList will have an index of 0.</p>
<pre><code class="language-java">	public void delete(int entry) {
		//your implementation here
        System.out.println(&quot;\nEntry #&quot; + entry + &quot; sucessfully deleted!&quot;);
	}
</code></pre>
<details close="">
  <summary>Answer</summary>
    <pre><code class="language-java">
    public void delete(int entry) {
		int index = entry - 1;
		list.remove(index);
		System.out.println("\nEntry #" + entry + " sucessfully deleted!");
	}
 </code></pre>
</details>
&nbsp;
<h2 id="puttingitalltogetherthecontactbookclientclass">Putting it all together - The ContactBookClient class</h2>
<p>Now that we've finished writing the code for the <code>Contact</code> and <code>Contact Book</code> classes, we are ready to implement our main method (ContactBookClient class) that allows the user to interact with our contact book program through the console. Once again, I will provide you with boilerplate code. I recommend you run the provided code first to get an idea of the expected output.<br>
You can either <a href="https://iq.opengenus.org/junit-testing-using-maven/">write your own unit tests</a> or run your program in the console to verify the output is correct. My full implementation is provided in the GitHub repo linked at the bottom of this article.</p>
<p>ContactBookClient.java</p>
<pre><code class="language-java">import java.util.InputMismatchException;
import java.util.Scanner;

public class ContactBookClient {

    private static Scanner s = new Scanner(System.in);

    public static void main(String[] args) {
        ContactBook contactBook = new ContactBook();
        int userInput;

        do {
            displayMenu();
            userInput = getValidMenuOption();

            switch (userInput) {
                case 1:
                    if (contactBook.getSize() != 0) {
                        //your code here
                    } else {
                        System.out.println(&quot;There are no contacts to view.&quot;);
                    }
                    break;
                case 2:
                    //your code here
                    break;
                case 3:
                    if (contactBook.getSize() != 0) {
                       //your code here
                    } else {
                        System.out.println(&quot;There are no contacts to edit.&quot;);
                    }
                    break;
                case 4:
                    if (contactBook.getSize() != 0) {
                          //your code here
                    } else {
                        System.out.println(&quot;There are no contacts to delete.&quot;);
                    }
                    break;
                case 5:
                    System.out.println(&quot;Exiting program...&quot;);
                    break;
                default:
                    System.out.println(&quot;Invalid option.&quot;);
            }
        } while (userInput != 5);

        s.close();
    }

    // Displays the menu options
    private static void displayMenu() {
        System.out.println(&quot;Contact Book Menu:&quot;);
        System.out.println(&quot;1 - View contacts&quot;);
        System.out.println(&quot;2 - Add a new contact&quot;);
        System.out.println(&quot;3 - Edit a contact&quot;);
        System.out.println(&quot;4 - Delete a contact&quot;);
        System.out.println(&quot;5 - Quit&quot;);
        System.out.print(&quot;Choose an option: &quot;);
    }

    // Gets a valid menu option between 1 and 5
    private static int getValidMenuOption() {
        int userInput = -1;
        boolean inputValid = false;

        do {
            try {
                userInput = s.nextInt();
                if (userInput &gt;= 1 &amp;&amp; userInput &lt;= 5) {
                    inputValid = true;
                } else {
                    System.out.println(&quot;Invalid input. Please enter a number between 1 and 5.&quot;);
                }
            } catch (InputMismatchException e) {
                System.out.println(&quot;Invalid input. Please enter a valid number.&quot;);
                s.next(); // Clear invalid input
            }
        } while (!inputValid);

        s.nextLine(); // Consume leftover newline
        return userInput;
    }

    // Adds a new contact to the contact book
    private static void addContact(ContactBook contactBook) {
        System.out.print(&quot;Enter contact name: &quot;);
        //read user input

        System.out.print(&quot;Enter contact email: &quot;);
       //read user input

        System.out.print(&quot;Enter contact phone number: &quot;);
        //read user input

        //add name, phone number, and email to contact book
        System.out.println(&quot;Contact added successfully.&quot;);
    }

    // Edits a contact from the contact book
    private static void editContact(ContactBook contactBook) {
        //process user input
        //edit the contact's information
        System.out.println(&quot;Contact edited successfully.&quot;);
    }

    // Deletes a contact from the contact book
    private static void deleteContact(ContactBook contactBook) {
         //process user input
         //delete the contact from the contact book
        System.out.println(&quot;Contact deleted successfully.&quot;);
    }

    //Processes user input to choose a valid entry from the contact book
     public static int processUserInput(ContactBook contactBook) {
        //implement this method following the same pattern as used in getValidMenuOption() 
       //if the input is invalid print a message to inform the user
       int userInput = -1;
       boolean inputInvalid;
                    
       do {
            System.out.print(&quot;Choose an entry (1 to &quot; + contactBook.getSize() + &quot;): &quot;);
            try {
               //your code here
                }
            } catch (InputMismatchException e) {
               //your code here
            }
        } while (inputInvalid);

        s.nextLine(); // Consume leftover newline
        return userInput;
    }
</code></pre>
<h2 id="summary">Summary</h2>
<p>In this article, I have demonstrated object-oriented programming (OOP) in action. By developing a simple contact book program, I hope you’ve gained a clearer understanding of the core concepts of OOP and how they can be applied in real-world programming.</p>
<h2 id="keyconcepts">Key concepts</h2>
<p>Class: A blueprint or template for creating objects. It defines the properties (fields) and behaviors (methods) that objects of that class will have.</p>
<p>Object: An instance of a class, representing a specific entity with its own set of values for the defined properties and methods.</p>
<p>Instance variable: A variable defined in a class for which each instantiated object (instance) of the class has its own copy.</p>
<p>Static: Describes a class member that belongs to the class itself rather than to any specific instance. Static members can be accessed directly using the class name, without needing to create an object first. Note that you cannot access non-static members from a static context.</p>
<p>Public: An access modifier that allows a class, method, or variable to be accessible from any other class.</p>
<p>Private: An access modifier that restricts access to a class's variables or methods to only within that class.</p>
<p>Encapsulation: The OOP principle of keeping data (variables) and methods together in a class and restricting direct access to some components using access modifiers like private.</p>
<p>Constructor: A special method in a class that is used to initialize new objects. It often sets the initial values of instance variables.</p>
<p>Getter: A method that retrieves or &quot;gets&quot; the value of a private instance variable.</p>
<p>Setter: A method that updates or &quot;sets&quot; the value of a private instance variable.</p>
<p>toString Method: A method that converts an object into a string representation, often for printing or debugging purposes.</p>
<p>equals Method: A method that compares two objects to determine if they are logically equal based on their content, rather than their memory addresses.</p>
<h2 id="resources">Resources</h2>
<p>Complete Implementation: <a href="https://github.com/skottchen/ContactBook">https://github.com/skottchen/ContactBook</a></p>
</div>]]></content:encoded></item><item><title><![CDATA[Exploring Randomness and Statistical Simulations in Online Games]]></title><description><![CDATA[The ever-changing online gaming world is built with randomness as an integral part. Randomness is needed because it gives variety and fun purely from the unpredictability of the fate of the characters' abilities.]]></description><link>https://iq.opengenus.org/exploring-randomness-and-statistical-simulations-in-online-games/</link><guid isPermaLink="false">6713a3e160f05005db557aaa</guid><dc:creator><![CDATA[Badal Srivastava]]></dc:creator><pubDate>Sat, 19 Oct 2024 12:38:27 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>The ever-changing online gaming world is built with randomness as an integral part. Randomness is needed because it gives variety and fun purely from the unpredictability of the fate of the characters' abilities.</p>
<p>However, the relentlessness of such simulations is built around a technical, rigorous framework beneath the randomness players put up with. These are fair and unpredictable; all players are on a level field.</p>
<h2 id="randomnessingamedesign">Randomness in Game Design</h2>
<p><img src="https://iq.opengenus.org/content/images/2024/10/game-console.jpg" alt="game-console"><br>
<a href="https://pixabay.com/photos/game-console-sony-video-games-6603120/">Pixabay</a></p>
<p>A big part of gaming is randomness, not just games of chance, but across a broad spectrum of gaming genres. Randomness is not always a bad thing, no matter if it's undoubtedly lucky whether an item drops in a role-playing game and then how to work out the probability of an outcome in strategy-based games.</p>
<p>It adds an element of surprise that turns engagement if done correctly. Randomness adds uncertainty, which keeps players on their toes and forces them to adapt and think on their feet.</p>
<p>The randomness created is based on random number generators (RNGs). RNGs simulate real-world unpredictability by generating random sequences that correspond to real-life events.</p>
<p>Without these systems, no two game experiences would be the same, ensuring players have fresh and dynamically spontaneous gameplay each time they interact with the game. Randomness is vital in traditional settings, such as online <a href="https://casino.netbet.it/">casino</a> games, so all are fair and captivated.</p>
<h2 id="statisticalsimulationsthebackboneoffairplay">Statistical Simulations: The Backbone of Fair Play</h2>
<p>Randomness is spontaneous, but it’s calculated in the most careful of ways through <a href="https://stattrek.com/experiments/simulation">statistical simulations</a>. Keeping these simulations around helps keep things fair because it puts an algorithmically balanced amount of luck and skill where needed. Statistical models simulate numerous odds and odds outcomes so the odds remain consistent and transparent.</p>
<p>While these simulations mimic unpredictability in online games, everything is planned out behind the scenes. Developers use statistics to adjust probabilities and game mechanics that keep players involved but not manipulated, relying on them.</p>
<h2 id="perceptionandfairnessaconstantstruggle">Perception and Fairness: A Constant Struggle</h2>
<p><img src="https://iq.opengenus.org/content/images/2024/10/pexels.jpg" alt="pexels"><br>
<a href="https://www.pexels.com/photo/men-in-gaming-tournament-19228385/">Pexels</a></p>
<p>Managing player perception in games that involve randomness is one of the ongoing challenges of game design. Even when RNGs and all other statistical models are 100% fair, players will sometimes perceive it as if the randomness is against them.</p>
<p>Here is where the psychological component comes into play: randomness. Creating an engaging experience with randomised content is a tricky balancing act that developers must remember: random outcomes must be fair.</p>
<p>Too predictable randomness may take the fun out of the game. If it feels chaotic enough, players could feel it’s unfair. One of the most challenging parts of game design is to <a href="https://www.gamedeveloper.com/design/design-101-balancing-games">strike the right balance</a> between those two extremes. The key is making randomness feel reasonable and making statistical simulations as transparent as possible.</p>
<h2 id="thesciencebehindrandomnessingames">The Science Behind Randomness in Games</h2>
<p>Randomness and statistical simulation produce positive, engaging, and unpredictable gaming experiences. These are the very concepts that make gameplay fair in traditional games, movies, or online platforms.</p>
<p>Game designers can achieve this by utilising statistical models and RNGs to offer the players an atmospheric space where skill and luck can coexist to produce an exciting dynamic.</p>
<p>However, randomness in online gaming has almost nothing to do with increasing uncertainty; it's about making the experience seem fair and well-balanced, regardless of the actual odds.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Dodgeball game in PyGame [with source code]]]></title><description><![CDATA[In this OpenGenus article, let us create a Dodgeball game in Python. You can customize your game along the way without having to stick to my design choices.]]></description><link>https://iq.opengenus.org/dodgeball-game-in-pygame/</link><guid isPermaLink="false">66a86059f232cd0570ca6c5d</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Sridevi Shankar]]></dc:creator><pubDate>Sun, 13 Oct 2024 15:50:49 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Game development is an exciting and interesting area to explore for people who have just finished learning web/app development, or any person who's enthusiastic about gaming and coding. To get started with game development, you must know at least one programming language such as C++, C#, Java or Python. Generally, to develop a 2D/3D game, it would be more convenient to learn a game engine so that much of the complexity of designing your game graphics, rendering audio, animation, etc. is abstracted. Keep in mind, game development requires many hours of creative and critical thinking to build up the logic for your game, consideration of all possible scenarios that can occur as well as delivering a smooth UX and a beautiful UI for the end users.</p>
<p>As a beginner who's never had any hands-on experience in game dev, you can use the PyGame library. It is a Python library that acts as a simple 2D gaming toolkit, providing features such as allowing you to draw sprites, providing support for sound, functionality for collision detection and more. It is, however, very rudimentary in comparison to other game engines which take into account physics, and help deal with advanced systems. But, it can be used to create beautiful and interesting games and is, most importantly, easy to learn and implement.</p>
<p>So, in this OpenGenus article, let us create a Dodgeball game in Python. You can customize your game along the way without having to stick to my design choices.</p>
<h2 id="tableofcontents">TABLE OF CONTENTS:</h2>
<h3 id="1basicsofpygame">1. Basics of PyGame</h3>
<h3 id="2settingupdodgeball">2. Setting up Dodgeball</h3>
<h3 id="3addingadditionalfunctionality">3. Adding additional functionality</h3>
<h3 id="4keytakeaways">4. Key takeaways</h3>
<p><strong>Pre-requisites</strong>: Knowledge of Python and Object-Oriented Programming in Python.</p>
<h2 id="1basicsofpygame">1. Basics of PyGame</h2>
<p>There are some basic concepts and terms that you'll need to know when you start using Pygame to build your game and we'll go over those in this section.</p>
<ul>
<li><strong>Surface</strong>- Is like a blank canvas in Pygame. You can fill color in it, put an image onto it or draw shapes on it.</li>
<li><strong>Screen</strong>- Is a special canvas in Pygame representing the game screen.</li>
<li><strong>Game Loop</strong>- Is the flow of control for the entire game. Keeps looping infinitely until a specific event occur, watches all input and handles it according to the programmed logic.</li>
<li><strong>Event</strong>- Is a certain action which occurs in the game duration upon trigger by the user or in a pre-programmed manner by the game itself.</li>
<li><strong>Sprite</strong>- Is an object which has attributes like size, color, etc. that can be customized as well as its own specific methods. Generally used to represent game characters as well as game objects.</li>
<li><strong>Rect</strong>- Represents a rectangular object that stores and manipulates rectangular areas. Used to control coordinates and movements.</li>
</ul>
<h2 id="2settingupdodgeball">2. Setting up Dodgeball</h2>
<p>Install the Pygame package by running pip install pygame. Once you've done that, paste this basic code snippet onto a new Python file in your project directory.</p>
<pre><code class="language-python">import pygame
import sys
# address delay in exiting the game from exit screen


# initializing pygame library
pygame.init()

                
# setting up game screen
WIDTH = 600
HEIGHT = 800

screen = pygame.display.set_mode([HEIGHT, WIDTH]) # provide a list or tuple to define the screen size


# handle game running
while True: # game loop- controls whether the program should be running or when it should quit
    # if user clicks exit window quit game
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT:
            # game_state = 0
            pygame.quit()
            sys.exit()
 
   
        # fill background color of screen: either a list or tuple is its argument
    screen.fill((137, 13, 15))
    
        # simply draw a circle on the screen
    pygame.draw.circle(screen, (0, 0, 0), (250, 250), 75)
    
  
    pygame.display.flip()
</code></pre>
<p>I have written detailed comments against each line to help you understand what is going on.<br>
We call pygame.init() so that pygame is able to initialize all its modules, and we define the screen size i.e. the size of the game window which the user interacts with. After that, we define our game loop which is essentially the loop that keeps the game running until the user wants to exit. If the user clicks the exit window, we use pygame.quit() to quit Pygame and sys.exit() to exit from the program. As for what is to be displayed on the game screen, for now we keep it simple and render a circle on the screen. The syntax of the command is pygame.draw.circle(screen (the game screen which we have defined), color to draw with, coordinates of the center, radius). Use pygame.display.flip() to render your graphics on the game window. I have also filled the screen with a dark-red color: rgb(137, 13, 15). Now when you run your Python program, you should be able to see the aforementioned details on the game window and when you click the exit icon, the game should stop and the window must close. What you will notice if everything went smoothly is that there is an infinite number of frames per second, we'll tackle that issue shortly and slow down the fps so that the game is playable in the upcoming section. In case you face any issues, cross-check your code and check the documentation to make sure you are using all the methods in the proper intended way and using the proper syntax.</p>
<p>We have succesfully set up the skeleton for our dodgeball game.</p>
<p>To break down all the features that should be present in our game, let us list them out:</p>
<ol>
<li>Render a player, and enemies (balls) as the main components.</li>
<li>Add audio to the game.</li>
<li>Add a score tracker to the game.</li>
<li>If a collision is detected the game must be ended.</li>
<li>Enemies (balls) must constantly fly at the player at a constant rate per level.</li>
</ol>
<p>Sprites in Pygame are objects with attributes and methods that represent our game characters.</p>
<p>We define the following classes in our game to modularize our code:</p>
<ol>
<li>Image - to load an image path and set its position on the screen</li>
</ol>
<pre><code class="language-python"># extend pygame.sprite.Sprite using super() (inheritance, returns a delegate object to the parent and extends its functionality)
class Image:
    def __init__(self, path):
    # load the image path and optimize it for fast blitting as well as preserve its transparent are
        self.avatar = pygame.image.load(path).convert_alpha()
        self.avatar.set_colorkey((255, 255, 255)) # sets a specific color to be treated as transparent
        self.avatar = pygame.transform.smoothscale(self.avatar, (100, 150)) # scales the image to a new size while preserving and providing higher quality resolution
        self.rect = self.avatar.get_rect(
            center = (
                20,
                HEIGHT/2
            )
        )
</code></pre>
<ol start="2">
<li>Game - to define the game player, define a group of enemies and a group of all the game sprites so that we can easily implement future functions which deal with those sprites in bulk, and load sound.</li>
</ol>
<pre><code class="language-python">class Game:
    def __init__(self):
        self.player = Player()
        self.enemies = pygame.sprite.Group()
        self.all_sprites = pygame.sprite.Group()
        self.all_sprites.add(self.player)
        self.limit = 5 # to help with our score logic, we use it as a lower bound to determine whether to increase our score or not
        self.passbys = 0 # number of balls that have successfully passed by without collision
        main_sound.play()
</code></pre>
<ol start="3">
<li>Player - we have images of the player for every direction it turns in, so here we would define the logic for changing the image of the player based on keyboard input and maintain the player's score as well.</li>
</ol>
<pre><code class="language-python">class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        image = Image(&quot;./positions/left.png&quot;)
        self.avatar = image.avatar
        self.rect = image.rect
        self.score = 0
    def update(self, pressed):
        if pressed[pygame.K_UP]:
            image = Image(&quot;./positions/up.png&quot;)
            self.avatar = image.avatar
            self.rect = self.avatar.get_rect(
                center = (
                    self.rect.centerx,
                    self.rect.centery - 10
                )
             )
            
        if pressed[pygame.K_DOWN]:
            image = Image(&quot;./positions/left.png&quot;)
            self.avatar = image.avatar
            self.rect = self.avatar.get_rect(
                center = (
                    self.rect.centerx,
                    self.rect.centery + 10
                )
             )
            
        if pressed[pygame.K_RIGHT]:
            image = Image(&quot;./positions/left.png&quot;)
            self.avatar = image.avatar
            self.rect = self.avatar.get_rect(
                center = (
                    self.rect.centerx + 10,
                    self.rect.centery 
                )
             )
            
        if pressed[pygame.K_LEFT]:
            image = Image(&quot;right.png&quot;)
            self.avatar = image.avatar
            self.rect = self.avatar.get_rect(
                center = (
                    self.rect.centerx - 10,
                    self.rect.centery
                )
             )
            
        # prevent player from hurtling off screen
        if self.rect.left &lt; 0:
            self.rect.left = 0
        if self.rect.top &lt;= 0:
            self.rect.top = 0
        if self.rect.right &gt; WIDTH:
            self.rect.right = WIDTH - 25
        if self.rect.bottom &gt;= HEIGHT:
            self.rect.bottom = HEIGHT - 25
</code></pre>
<ol start="4">
<li>Enemy - we load the enemy image and define its position on the game screen.</li>
</ol>
<pre><code class="language-python">class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.x = 20
        self.y = 10
        self.avatar = pygame.image.load(&quot;enemy.jpg&quot;).convert()
        self.avatar.set_colorkey((255, 255, 255))
        self.avatar = pygame.transform.scale(self.avatar, (80, 80))
        self.rect = self.avatar.get_rect(
            center = (
                random.randint(WIDTH + 20, WIDTH + 100),
                random.randint(0, HEIGHT)
            )
        )
        self.speed = random.randint(5, 20)
    def update(self):
        self.rect.move_ip(-self.speed, 0)
        if self.rect.right &lt; 0:
            self.kill()

</code></pre>
<p>What about the logic for collision and for rendering enemies (balls) periodically on the screen? What if the balls go out of frame- will they still be shown on the game screen?</p>
<p>To handle the logic for collision within the game loop, we typically implement that inside our game loop and using Pygame's inbuilt spritecollideany(sprite1, sprite2) function, we kill the player, stop the retro sound and play the collision sound effect, we render a new screen displaying the player's final score, wait for a few seconds and ask the player whether they are interested to try again, if not quit pygame and exit, else we continue the game loop.<br>
In addition, I have removed the circle and background color used for explanation in the previous section and replaced them with a bg image.</p>
<pre><code class="language-python">    pressed = pygame.key.get_pressed()
    game.player.update(pressed) # player's image changes based on direction
    game.enemies.update()  # enemy should whizz across the screen from the right to
    # the left and get killed when it goes out of frame
    background = pygame.image.load(&quot;bgimage.jpg&quot;)
    background = pygame.transform.scale(background, (HEIGHT, WIDTH))
    screen.fill((255, 255, 255))
    bg_rect = background.get_rect() 
    screen.blit(background, bg_rect) # rendering the bg image (image of the 
    # dodgeball court) on our game screen
    for entity in game.all_sprites: # game.all_sprites is a list of all sprite objects
        screen.blit(entity.avatar, entity.rect) # draws the entity's image onto the # surface defined for it
    # check for collisions
    if pygame.sprite.spritecollideany(game.player, game.enemies):
        # you lose! try again page
        game.player.kill()
        main_sound.stop()
        collision_sound.play()
        if event.type == pygame.K_ESCAPE:
            pygame.quit()
            sys.exit()
        else:
            game = Game()
            continue
        # flip display- updates contents of display to the screen, without this nothing appears
    pygame.display.flip()
    clock.tick(30) # program should maintain a rate of 30 fps
</code></pre>
<p>To use different game screens based on whether the player has lost or quit or just begun the game, we can use Pygame's render method to display the player's current score and show them that they have lost, and create a new screen to ask the player whether they wish to try again or quit:</p>
<pre><code class="language-python">        loser = pygame.font.Font('Micro5-Regular.ttf', 50)
        new_surf = loser.render(f&quot;You lost! Your final score is {game.player.score}.&quot;, False, (255, 68, 51)) # create a surface off the text
        screen.blit(new_surf, (WIDTH/3, HEIGHT/2))
        pygame.display.flip()
        pygame.time.wait(1000)
        screen = pygame.display.set_mode([HEIGHT, WIDTH])
        screen.fill((144, 238, 144))
        intro_screen = pygame.font.Font('your_font.ttf', 70)
        intro = intro_screen.render(&quot;Try again? Press ESC to exit or wait to restart&quot;, False, (255, 68, 51))
        screen.blit(intro, (10, HEIGHT/5))
        pygame.display.flip()
        pygame.time.wait(2000)
</code></pre>
<p>For rendering enemies, we want our enemies i.e. the balls to constantly come into frame from the right as they do in dodgeball. To tackle this, we define a new event called ADD_ENEMY and use set_timer to have a constant influx of enemies after a pre-defined interval.</p>
<pre><code class="language-python">''' now we have to create a steady supply of enemies aka obstacles at regular intervals- create a custom event
and set its interval '''
ADD_ENEMY = pygame.USEREVENT + 1
pygame.time.set_timer(ADD_ENEMY, 1000)
</code></pre>
<p>We add the event-handling logic for it within the game loop :</p>
<pre><code class="language-python">elif event.type == ADD_ENEMY:
                new_enemy = Enemy()
                game.enemies.add(new_enemy)
                game.all_sprites.add(new_enemy)
                game.passbys += 1
                if game.passbys &gt; game.limit:
                    game.player.score += 5
                    game.limit += 5
                print(game.player.score)
</code></pre>
<p>Lo and behold, the game is ready!</p>
<p><img src="https://iq.opengenus.org/content/images/2024/08/Screenshot--611-.png" alt="Game Being Played"></p>
<p><img src="https://iq.opengenus.org/content/images/2024/08/Screenshot--613-.png" alt="Player Lost"></p>
<p><img src="https://iq.opengenus.org/content/images/2024/08/Screenshot--614-.png" alt="Try Again Screen"></p>
<h2 id="3addingadditionalfunctionality">3. Adding additional functionality</h2>
<p>Here are some suggestions for you to practice all you have learnt about PyGame so far, you can add on some additional features to the game and refer to the documentation as and when you get stuck.</p>
<ol>
<li>Implement a level feature- if your score hits a threshold, you get to a higher level and update the threshold. At each level upgrade, the speed of the incoming balls increases and it gets more difficult to score.</li>
<li>Implement a dark mode level- once you have reached a sufficiently high level, you can make the court go dark as if someone has switched off the lights and focus a spotlight on the player, and one on the incoming ball.</li>
<li>Add different ball types- instead of having the same type of ball coming in, you can add an extra bouncy ball, a super slow ball, a super fast one as well as one with a very large stride.</li>
<li>Add bonuses- you can increase the player's score by a large amount if they manage to avoid colliding with a special ball such as one that is very fast/extra bouncy.</li>
<li>Add a high score feature- Keep track of the highest score that the player has achieved till now.</li>
<li>Implement a tutorial mode- Show the player how the game is meant to be played and what the game's rules are by implementing a simple tutorial before starting the game. Add an option to skip it as well.</li>
</ol>
<h2 id="keytakeaways">Key takeaways</h2>
<ul>
<li>
<p>Introduction to Game Development:</p>
<ul>
<li>Game development is ideal for those familiar with web/app development or coding enthusiasts.</li>
<li>Requires knowledge of programming languages (C++, C#, Java, Python).</li>
<li>Learning a game engine is beneficial for handling game graphics, audio, and animation.</li>
</ul>
</li>
<li>
<p>About PyGame:</p>
<ul>
<li>PyGame is a Python library for 2D game development.</li>
<li>It simplifies creating games with features like sprite drawing, sound support, and collision detection.</li>
</ul>
</li>
<li>
<p>Creating a Dodgeball Game:</p>
<ul>
<li>
<p>Basics of PyGame:</p>
<ul>
<li>Install PyGame and set up a basic game window with pygame.init().</li>
<li>Basic code includes setting up the game loop, handling events, and rendering graphics.</li>
</ul>
</li>
<li>
<p>Setting Up Dodgeball:</p>
<ul>
<li>Features include rendering player and enemies, adding audio, scoring, and handling collisions.</li>
<li>Use classes for game elements: Image, Game, Player, and Enemy.</li>
<li>Implement collision detection and different game screens.</li>
<li>Add functionality to periodically generate enemies and manage fps.</li>
</ul>
</li>
<li>
<p>Adding Additional Functionality:</p>
<ul>
<li>Suggestions include implementing levels, dark mode, different ball types, bonuses, high scores, and a tutorial mode.</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>]]></content:encoded></item></channel></rss>