0% found this document useful (0 votes)
17 views

AI File

Uploaded by

divine rocky
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views

AI File

Uploaded by

divine rocky
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 30

Task 1: Learn the building blocks of Logic Programming in Python.

Logic programming is a paradigm that focuses on using logical relationships to express


computation. In Python, you can implement logic programming using libraries like PyDatalog
or PrologPy. Here are the fundamental building blocks:
1.Facts: Facts are basic statements about the problem domain. In logic programming, facts are
often represented as predicates. For example, in a family tree program, a fact could be "John is
the father of Mary."
2.Rules: Rules define relationships between facts. They specify how new information can be
derived from existing information. For example, a rule in a family tree program could be "A
person X is the parent of person Y if X is the father or mother of Y."
3.Queries: Queries are questions or goals that you want the program to answer. You can query
the program to find information based on the facts and rules you've provided. For example, you
might query "Who are the children of John?"
4.Variables: Variables are placeholders that can take on different values. They are used in rules
and queries to represent unknowns or to generalize patterns. For example, in the query "Who
are the children of John?", the variable could be used to represent the children.
5.Unification: Unification is the process of finding values for variables that make two
expressions equal. It's a fundamental operation in logic programming. For example, if you have
a rule "A is the parent of B if A is the father of B," and you query "Who are the parents of
Mary?" the system needs to unify "A" with "John" and "B" with "Mary" to find the answer.

1
Task 2: Python script for comparing mathematical expressions and finding
out unknown values.

from sympy import symbols, Eq, solve


def solve_expression(expression1, expression2):
x = symbols('x')
eq1 = Eq(eval(expression1), x)
eq2 = Eq(eval(expression2), x)
solution = solve((eq1, eq2), (x))
if solution:
return solution[x]
else:
return "No solution found"
# Example usage:
expression1 = "2*x + 5"
expression2 = "3*x - 2"
result = solve_expression(expression1, expression2)
print("Value of x:", result)
Output

2
Task3: Use logic programming in Python to check for prime numbers.

num = 29
# To take input from the user
#num = int(input("Enter a number: "))
# define a flag variable
flag = False
if num == 1:
print(num, "is not a prime number")
elif num > 1:
# check for factors
for i in range(2, num):
if (num % i) == 0:
# if factor is found, set flag to True
flag = True
# break out of loop
break
# check if flag is True
if flag:
print(num, "is not a prime number")
else:
print(num, "is a prime number"”)
Output

3
Task4: Use logic programming in Python parse a family tree and infer the
relationships between the family members.

from pyDatalog import pyDatalog


# Define family relationships
pyDatalog.create_terms('parent, sibling, grandparent, uncle, aunt, cousin')
# Define family tree
+parent('John', 'Mary')
+parent('John', 'Tom')
+parent('Mary', 'Alice')
+parent('Mary', 'Bob')
+parent('Tom', 'Charlie')
+parent('Alice', 'David')
+parent('Bob', 'Eve')
# Define rules for sibling relationship
sibling(X, Y) <= (parent(Z, X) & parent(Z, Y) & (X != Y))
# Define rules for grandparent relationship
grandparent(X, Y) <= (parent(X, Z) & parent(Z, Y))
# Define rules for uncle relationship
uncle(X, Y) <= (parent(Z, Y) & sibling(X, Z) & (X != Y) & (Z != Y))
# Define rules for aunt relationship
aunt(X, Y) <= (parent(Z, Y) & sibling(X, Z) & (X != Y) & (Z != Y))
# Define rules for cousin relationship
cousin(X, Y) <= (parent(Z, X) & aunt(W, Z) & parent(W, Y) & (X != Y) & (W != X) & (W
!= Y))
# Query relationships
print("Siblings:", set(sibling(X, Y) for X, Y in sibling(X, Y)))
print("Grandparents:", set(grandparent(X, Y) for X, Y in grandparent(X, Y)))
print("Uncles:", set(uncle(X, Y) for X, Y in uncle(X, Y)))
print("Aunts:", set(aunt(X, Y) for X, Y in aunt(X, Y)))
print("Cousins:", set(cousin(X, Y) for X, Y in cousin(X, Y)))

4
Task5: Python script for building a puzzle solver.

import copy
# Importing the heap functions from python
# library for Priority Queue
from heapq import heappush, heappop
# This variable can be changed to change
# the program from 8 puzzle(n=3) to 15
# puzzle(n=4) to 24 puzzle(n=5)...
n=3
# bottom, left, top, right
row = [ 1, 0, -1, 0 ]
col = [ 0, -1, 0, 1 ]
# A class for Priority Queue
class priorityQueue:
# Constructor to initialize a
# Priority Queue
def init (self):
self.heap = []
# Inserts a new key 'k'
def push(self, k):
heappush(self.heap, k)
# Method to remove minimum element
# from Priority Queue
def pop(self):
return heappop(self.heap)
# Method to know if the Queue is empty
def empty(self):
if not self.heap:
return True
else:

5
return False
# Node structure
class node:
def init (self, parent, mat, empty_tile_pos, cost, level):
# Stores the parent node of the
# current node helps in tracing
# path when the answer is found
self.parent = parent
# Stores the matrix
self.mat = mat
# Stores the position at which the
# empty space tile exists in the matrix
self.empty_tile_pos = empty_tile_pos
# Stores the number of misplaced tiles
self.cost = cost
# Stores the number of moves so far
self.level = level
# This method is defined so that the
# priority queue is formed based on
# the cost variable of the objects
def lt (self, nxt):
return self.cost < nxt.cost
# Function to calculate the number of
# misplaced tiles ie. number of non-blank
# tiles not in their goal position
def calculateCost(mat, final) ->int:
count = 0
for i in range(n):
for j in range(n):
if ((mat[i][j]) and

6
(mat[i][j] != final[i][j])):
count += 1
return count
def newNode(mat, empty_tile_pos, new_empty_tile_pos,
level, parent, final) -> node:
# Copy data from parent matrix to current matrix
new_mat = copy.deepcopy(mat)
# Move tile by 1 position
x1 = empty_tile_pos[0]
y1 = empty_tile_pos[1]
x2 = new_empty_tile_pos[0]
y2 = new_empty_tile_pos[1]
new_mat[x1][y1], new_mat[x2][y2] = new_mat[x2][y2], new_mat[x1][y1]
# Set number of misplaced tiles
cost = calculateCost(new_mat, final)
new_node = node(parent, new_mat, new_empty_tile_pos, cost, level)
return new_node
# Function to print the N x N matrix
def printMatrix(mat):
for i in range(n):
for j in range(n):
print("%d " % (mat[i][j]), end = " ")
print()
# Function to check if (x, y) is a valid
# matrix coordinate
def isSafe(x, y):
return x >= 0 and x < n and y >= 0 and y < n
# Print path from root node to destination node def printPath(root):
if root == None:
returrn

7
printPath(root.parent)
printMatrix(root.mat)
print()
# Function to solve N*N - 1 puzzle algorithm
# using Branch and Bound. empty_tile_pos is
# the blank tile position in the initial state.
def solve(initial, empty_tile_pos, final):
# Create a priority queue to store live
# nodes of search tree
pq = priorityQueue()
# Create the root node
cost = calculateCost(initial, final)
root = node(None, initial,empty_tile_pos, cost, 0)
# Add root to list of live nodes
pq.push(root)
# Finds a live node with least cost,
# add its children to list of live
# nodes and finally deletes it from
# the list.
while not pq.empty():
# Find a live node with least estimated
# cost and delete it from the list of
# live nodes
minimum = pq.pop()
# If minimum is the answer node
if minimum.cost == 0:
# Print the path from root to
# destination;
printPath(minimum)
return

8
# Generate all possible children
for i in range(4):
new_tile_pos = [
minimum.empty_tile_pos[0] + row[i],
minimum.empty_tile_pos[1] + col[i], ]
if isSafe(new_tile_pos[0], new_tile_pos[1]):
# Create a child node
child = newNode(minimum.mat, minimum.empty_tile_pos, new_tile_pos, minimum.level +
1, minimum, final,)
# Add child to list of live nodes
pq.push(child)
# Driver Code
# Initial configuration
# Value 0 is used for empty space
initial = [ [ 1, 2, 3 ],
[ 5, 6, 0 ],
[ 7, 8, 4 ],
# Solvable Final configuration
# Value 0 is used for empty space
final = [ [ 1, 2, 3 ],
[ 5, 8, 6 ],
[ 0, 7, 4 ] ]
# Blank tile coordinates in
# initial configuration
empty_tile_pos = [ 1, 2 ]
# Function call to solve the puzzle
solve(initial, empty_tile_pos, final)

9
Output

10
Task6: Implementation of Naïve Bayes classifier, computing its accuracy
and visualizing its performance.

Def calc_statistics(self, features, target):


'''
calculate mean, variance for each column and convert to numpy array
'''
self.mean = features.groupby(target).apply(np.mean).to_numpy()
self.var = features.groupby(target).apply(np.var).to_numpy()
return self.mean, self.var
def gaussian_density(self, class_idx, x):
'''
calculate probability from gaussian density function (normally distributed)
'''
mean = self.mean[class_idx]
var = self.var[class_idx]
numerator = np.exp((-1/2)*((x-mean)**2) / (2 * var))
denominator = np.sqrt(2 * np.pi * var)
prob = numerator / denominator
return prob
# prior probabilities
def calc_prior(self, features, target):
self.prior = (features.groupby(target).apply(lambda x: len(x))/self.rows).to_numpy()
return self.prior
# posterior probabilities
def calc_posterior(self, x):
posteriors = []
for i in range(self.count):
prior = np.log(self.prior[i])
conditional = np.sum(np.log(self.gaussian_density(i, x)))
posterior = prior + conditional

11
posteriors.append(posterior)
return self.classes[np.argmax(posteriors)]
def fit(self, features, target):
# define class variables
self.classes = np.unique(target)
self.count = len(self.classes)
self.feature_nums = features.shape[1]
self.rows = features.shape[0]
# calculate statistics
self.calc_statistics(features, target)
self.calc_prior(features, target)
def predict(self, features):
preds = [self.calc_posterior(f) for f in features.to_numpy()]
return preds
output

12
Task7: Creation of a fuzzy control system which models how you might
choose to tip at a restaurant.

import numpy as np
import skfuzzy as fuzz
from skfuzzy import control as ctrl
# Define input variables
service = ctrl.Antecedent(np.arange(0, 11, 1), 'service')
food = ctrl.Antecedent(np.arange(0, 11, 1), 'food')
# Define output variable
tip = ctrl.Consequent(np.arange(0, 26, 1), 'tip')
# Define membership functions
service['poor'] = fuzz.trimf(service.universe, [0, 0, 5])
service['average'] = fuzz.trimf(service.universe, [0, 5, 10])
service['excellent'] = fuzz.trimf(service.universe, [5, 10, 10])
food['bad'] = fuzz.trimf(food.universe, [0, 0, 5])
food['decent'] = fuzz.trimf(food.universe, [0, 5, 10])
food['delicious'] = fuzz.trimf(food.universe, [5, 10, 10])
tip['low'] = fuzz.trimf(tip.universe, [0, 0, 13])
tip['medium'] = fuzz.trimf(tip.universe, [0, 13, 25])
tip['high'] = fuzz.trimf(tip.universe, [13, 25, 25])# Define fuzzy rules
rule1 = ctrl.Rule(service['poor'] | food['bad'], tip['low'])
rule2 = ctrl.Rule(service['average'] | food['decent'], tip['medium'])
rule3 = ctrl.Rule(service['excellent'] | food['delicious'], tip['high'])# Create control system
tipping_ctrl = ctrl.ControlSystem([rule1, rule2, rule3])
tipping = ctrl.ControlSystemSimulation(tipping_ctrl)# Input values tipping.input['service'] =
6
tipping.input['food'] = 9# Compute tipping tipping.compute()
Output

13
Task 8: Implementation of uninformed search techniques in Python.

Breath First Search(BFS)


import collections
# BFS algorithm
def bfs(graph, root):
visited, queue = set(), collections.deque([root])
visited.add(root)
while queue:
# Dequeue a vertex from queue
vertex = queue.popleft()
print(str(vertex) + " ", end="")
# If not visited, mark it as visited, and
# enqueue it
for neighbour in graph[vertex]:
if neighbour not in visited:
visited.add(neighbour)
queue.append(neighbour)
if _ name__== ' main ':
graph = {0: [1, 2], 1: [2], 2: [3], 3: [1, 2]}
print("Following is Breadth First Traversal: ")
bfs(graph, 0)
Output

14
Depth First Search(DFS)
# DFS algorithm in Python
# DFS algorithm
def dfs(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
print(start)
for next in graph[start] - visited:
dfs(graph, next, visited)
return visited
graph = {'0': set(['1', '2']),
'1': set(['0', '3', '4']),
'2': set(['0']),
'3': set(['1']),
'4': set(['2', '3'])}
dfs(graph, '0')
Output

15
Task 9: Implementation of heuristic search techniques in Python.

import math
import heapq
# Define the Cell class
class Cell:
def init (self):
self.parent_i = 0 # Parent cell's row index
self.parent_j = 0 # Parent cell's column index
self.f = float('inf') # Total cost of the cell (g + h)
self.g = float('inf') # Cost from start to this cell
self.h = 0 # Heuristic cost from this cell to destination
# Define the size of the grid
ROW = 9
COL = 10
# Check if a cell is valid (within the grid)
def is_valid(row, col):
return (row >= 0) and (row < ROW) and (col >= 0) and (col < COL)
# Check if a cell is unblocked
def is_unblocked(grid, row, col):
return grid[row][col] == 1
# Check if a cell is the destination
def is_destination(row, col, dest):
return row == dest[0] and col == dest[1]
# Calculate the heuristic value of a cell (Euclidean distance to destination)
def calculate_h_value(row, col, dest):
return ((row - dest[0]) ** 2 + (col - dest[1]) ** 2) ** 0.5
# Trace the path from source to destination
def trace_path(cell_details, dest):
print("The Path is ")
path = []

16
row = dest[0]
col = dest[1]
# Trace the path from destination to source using parent cells
while not (cell_details[row][col].parent_i == row and cell_details[row][col].parent_j== col):
path.append((row, col))
temp_row = cell_details[row][col].parent_i
temp_col = cell_details[row][col].parent_j
row = temp_row
col = temp_col
# Add the source cell to the path
path.append((row, col))
# Reverse the path to get the path from source to destination
path.reverse()
# Print the path
for i in path:
print("->", i, end=" ") print()
# Implement the A* search algorithm
def a_star_search(grid, src, dest):
# Check if the source and destination are valid
if not is_valid(src[0], src[1]) or not is_valid(dest[0], dest[1]):
print("Source or destination is invalid")
return
# Check if the source and destination are unblocked
if not is_unblocked(grid, src[0], src[1]) or not is_unblocked(grid, dest[0], dest[1]):
print("Source or the destination is blocked")
return
# Check if we are already at the destination
if is_destination(src[0], src[1], dest):
print("We are already at the destination")
return
# Initialize the closed list (visited cells)

17
closed_list = [[False for _ in range(COL)] for _ in range(ROW)]
# Initialize the details of each cell
cell_details = [[Cell() for _ in range(COL)] for _ in range(ROW)]
# Initialize the start cell details
i = src[0]
j = src[1]
cell_details[i][j].f = 0
cell_details[i][j].g = 0
cell_details[i][j].h = 0
cell_details[i][j].parent_i = i
cell_details[i][j].parent_j = j
# Initialize the open list (cells to be visited) with the start cell
open_list = []
heapq.heappush(open_list, (0.0, i, j))
# Initialize the flag for whether destination is found
found_dest = False
# Main loop of A* search algorithm
while len(open_list) > 0:
# Pop the cell with the smallest f value from the open list
p = heapq.heappop(open_list)
# Mark the cell as visited
i = p[1]
j = p[2]
closed_list[i][j] = True
# For each direction, check the successors
directions = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]
for dir in directions:
new_i = i + dir[0]
new_j = j + dir[1]

18
# If the successor is valid, unblocked, and not visited
if is_valid(new_i, new_j) and is_unblocked(grid, new_i, new_j) and not
closed_list[new_i][new_j]:
# If the successor is the destination
if is_destination(new_i, new_j, dest):
# Set the parent of the destination cell
cell_details[new_i][new_j].parent_i = i
cell_details[new_i][new_j].parent_j = j
print("The destination cell is found")
# Trace and print the path from source to destination
trace_path(cell_details, dest)
found_dest = True
return
else:
# Calculate the new f, g, and h values
g_new = cell_details[i][j].g + 1.0
h_new = calculate_h_value(new_i, new_j, dest)
f_new = g_new + h_new
# If the cell is not in the open list or the new f value is smaller
if cell_details[new_i][new_j].f == float('inf') or cell_details[new_i][new_j].f >
f_new:
# Add the cell to the open list
heapq.heappush(open_list, (f_new, new_i, new_j))
# Update the cell details
cell_details[new_i][new_j].f = f_new
cell_details[new_i][new_j].g = g_new
cell_details[new_i][new_j].h = h_new
cell_details[new_i][new_j].parent_i = i
cell_details[new_i][new_j].parent_j = j

19
# If the destination is not found after visiting all cells if not found_dest:
print("Failed to find the destination cell")
def main():
# Define the grid (1 for unblocked, 0 for blocked) grid = [
[1, 0, 1, 1, 1, 1, 0, 1, 1, 1],
[1, 1, 1, 0, 1, 1, 1, 0, 1, 1],
[1, 1, 1, 0, 1, 1, 0, 1, 0, 1],
[0, 0, 1, 0, 1, 0, 0, 0, 0, 1],
[1, 1, 1, 0, 1, 1, 1, 0, 1, 0],
[1, 0, 1, 1, 1, 1, 0, 1, 0, 0],
[1, 0, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 0, 1, 1, 1],
[1, 1, 1, 0, 0, 0, 1, 0, 0, 1]
]
# Define the source and destination
src = [8, 0]
dest = [0, 0]
# Run the A* search algorithm
a_star_search(grid, src, dest)
if __ name== " main ": main()
Output

20
Task10: Python script for tokenizing text data.

from nltk.corpus import stopwords


en_stops = set(stopwords.words('english'))
all_words = ['There', 'is', 'a', 'tree','near','the','river']
for word in all_words:
if word not in en_stops:
print(word)
Output

21
Task11: Extracting the frequency of terms using a Bag of Words model.
from collections import Counter
import re
def tokenize(text):
# Split the text into individual words while removing punctuation
tokens = re.findall(r'\b\w+\b', text.lower())
return tokens
def build_vocab(tokenized_texts):
# Create a vocabulary of unique words
vocab = set()
for tokens in tokenized_texts:
vocab.update(tokens)
# Assign an index to each word in the vocabulary
vocab_to_index = {word: i for i, word in enumerate(vocab)}
return vocab_to_index
def count_word_frequencies(tokenized_text, vocab):
# Count the frequency of each word in the vocabulary
word_freq = Counter(tokenized_text)
# Convert word frequencies to a vector representation
vector = [word_freq[word] for word in vocab]
return vector
# Example text data
text_data = [
"This is a sample sentence.",
"Another example sentence.",
"Yet another example for demonstration."
]
# Tokenize the text data
tokenized_texts = [tokenize(text) for text in text_data]

22
# Build the vocabulary
vocab = build_vocab(tokenized_texts)
# Count word frequencies for each document
for i, tokens in enumerate(tokenized_texts):
word_freq_vector = count_word_frequencies(tokens, vocab)
print(f"Document {i+1} word frequency vector: {word_freq_vector}")
tokenize() function splits the text into individual words, build_vocab() function creates a
vocabulary, and count_word_frequencies() function counts the frequency of each word in the
vocabulary for each document.

23
Task12: Predict the category to which a given piece of text belongs.
To predict the category to which a given piece of text belongs, you can use a machine
learning classifier trained on labeled text data. Here's a general approach:
1.Data Collection and Preprocessing: Gather a dataset where each piece of text is labeled
with its corresponding category. Preprocess the text data by tokenizing it, removing
stopwords, and converting it into a numerical representation.
2.Feature Extraction: Use techniques like TF-IDF (Term Frequency-Inverse Document
Frequency) or word embeddings to represent the text data in a numerical format suitable for
machine learning algorithms.
3.Model Training: Train a classifier such as Naive Bayes, Support Vector Machine (SVM), or
a neural network on the labeled text data. Use techniques like cross-validation to tune
hyperparameters and avoid overfitting.
4.Prediction: Once the model is trained, you can use it to predict the category of new pieces
of text by transforming the text into the same numerical format used during training and then
feeding it into the trained classifier.
Here's a basic example using Python and scikit-learn library with a TF-IDF vectorizer and a
Multinomial Naive Bayes classifier:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import make_pipeline
# Example labeled text data
text_data = [
("This is a sample sentence.", "Category1"),
("Another example sentence.", "Category2"),
("Yet another example for demonstration.", "Category1")
]
# Separate text and labels
texts, labels = zip(*text_data)
# Create a pipeline with TF-IDF vectorizer and Multinomial Naive Bayes classifier
model = make_pipeline(TfidfVectorizer(), MultinomialNB())
# Train the model
model.fit(texts, labels)
# Example text to predict its category
new_text = "A new sentence for prediction."

24
# Predict the category of the new text
predicted_category = model.predict([new_text])
print("Predicted category:", predicted_category[0])
In this example, we use a Multinomial Naive Bayes classifier trained on TF-IDF vectors of
text data to predict the category of a new piece of text. You can replace MultinomialNB with
other classifiers and experiment with different feature extraction techniques to improve
performance. Additionally, for real-world applications, you may need larger and more diverse
datasets and more sophisticated models.

25
Task13: Python code for visualizing audio speech signal.
# imports
import matplotlib.pyplot as plt import numpy as np
import wave, sys
# shows the sound waves
def visualize(path: str):
# reading the audio file
raw = wave.open(path)
# reads all the frames
# -1 indicates all or max frames
signal = raw.readframes(-1)
signal = np.frombuffer(signal, dtype =”int16”)
# gets the frame rate
f_rate = raw.getframerate()
# to Plot the x-axis in seconds
# you need get the frame rate
# and divide by size of your signal
# to create a Time Vector
# spaced linearly with the size
# of the audio file
time = np.linspace(
0, # start
len(signal) / f_rate, num = len(signal)
)
# using matplotlib to plot
# creates a new figure
plt.figure(1)
# title of the plot
plt.title(“Sound Wave”)
# label of x-axis

26
plt.xlabel(“Time”)
# actual plotting
plt.plot(time, signal)
# shows the plot
# in new window
plt.show()
# you can also save
# the plot using
# plt.savefig(‘filename’)
If__ name== “ main ”:
# gets the command line Value
path = sys.argv[1]
visualize(path)
Output

27
Task14: Python code for Generating audio signals.
import numpy as np
import scipy.io.wavfile as wav
# Sampling rate (samples per second)
sample_rate = 44100
# Duration of the audio signal (in seconds)
duration = 5.0
# Frequency of the sine wave (in Hz)
frequency = 440.0 # A4 note
# Time points
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
# Generate the audio signal (sine wave)
audio_signal = np.sin(2 * np.pi * frequency * t)
# Normalize the audio signal to the range [-1, 1]
audio_signal /= np.max(np.abs(audio_signal))
# Save the audio signal as a WAV file
wav.write("sine_wave.wav", sample_rate, audio_signal)
In this example:
•We define the sampling rate (sample_rate) which determines the number of samples per
second.
•We specify the duration of the audio signal (duration) in seconds.
•We set the frequency of the sine wave (frequency) in Hertz (Hz).
•We create an array of time points (t) using np.linspace() to represent the time axis of the
audio signal.
•We generate the audio signal by computing the sine wave using np.sin() with the desired
frequency.
•We normalize the audio signal to the range [-1, 1] to ensure it is within the valid range for a
PCM (Pulse Code Modulation) audio signal.
•Finally, we save the audio signal as a WAV file using scipy.io.wavfile.write().

28
Task15: Python code for Synthesizing tones to generate music.
import numpy as np
import scipy.io.wavfile as wav
# Function to generate a sine wave tone of a given frequency and duration
def generate_tone(frequency, duration, sample_rate):
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
return np.sin(2 * np.pi * frequency * t)
# Sampling rate (samples per second)
sample_rate = 44100
# Duration of each note (in seconds)
note_duration = 0.5
# Define musical notes and their corresponding frequencies (in Hz)
notes = {
"C4": 261.63,
"D4": 293.66,
"E4": 329.63,
"F4": 349.23,
"G4": 392.00,
"A4": 440.00,
"B4": 493.88,
"C5": 523.25
}
# Define a simple melody (sequence of notes)
melody = ["C4", "D4", "E4", "F4", "G4", "A4", "B4", "C5"]
# Generate audio signal for the melody
audio_signal = np.concatenate([generate_tone(notes[note], note_duration, sample_rate) for
note in melody])
# Normalize the audio signal to the range [-1, 1]
audio_signal /= np.max(np.abs(audio_signal))
# Save the audio signal as a WAV file
wav.write("simple_melody.wav", sample_rate, audio_signal)

29
In this example:
•We define a function generate_tone() to generate a sine wave tone of a given frequency and
duration.
•We specify the sampling rate (sample_rate) in samples per second.
•We define the duration of each note (note_duration) in seconds.
•We define musical notes and their corresponding frequencies in the notes dictionary.
•We define a simple melody as a sequence of note names.
•We generate the audio signal for the melody by concatenating sine wave tones for each note
in the melody.
•Finally, we normalize the audio signal and save it as a WAV file.

30

You might also like