Compare commits
4 Commits
923dd2e2a5
...
de50816932
Author | SHA1 | Date |
---|---|---|
Citlali del Rey | de50816932 | |
Citlali del Rey | 1bf67d7ee3 | |
Citlali del Rey | 10c0d9d5dd | |
Citlali del Rey | 79550d0612 |
After Width: | Height: | Size: 230 KiB |
|
@ -0,0 +1,116 @@
|
|||
%! TeX program = lualatex
|
||||
\RequirePackage[l2tabu,orthodox]{nag}
|
||||
\DocumentMetadata{lang=en-US}
|
||||
\documentclass[a4paper]{scrarticle}
|
||||
\usepackage{geometry}
|
||||
%\usepackage{tikz}
|
||||
%\usepackage{tikz-uml}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{caption}
|
||||
\usepackage{bookmark}
|
||||
\usepackage{fontspec}
|
||||
\usepackage{microtype}
|
||||
\usepackage{graphicx}
|
||||
|
||||
% Math packages
|
||||
%\usepackage{amsmath}
|
||||
%\usepackage{mathtools}
|
||||
%\usepackage{amsthm}
|
||||
%\usepackage{thmtools}
|
||||
%\usepackage{lualatex-math}
|
||||
|
||||
% Unicode Math
|
||||
\usepackage[warnings-off={mathtools-colon,mathtools-overbracket},math-style=ISO]{unicode-math}
|
||||
\usepackage{newcomputermodern}
|
||||
|
||||
\newcommand*{\figref}[2][]{%
|
||||
\hyperref[{fig:#2}]{%
|
||||
Figure~\ref*{fig:#2}%
|
||||
\ifx\\#1\\%
|
||||
\else
|
||||
\,#1%
|
||||
\fi
|
||||
}%
|
||||
}
|
||||
|
||||
%\DeclarePairedDelimiter\ceil{\lceil}{\rceil}
|
||||
%\DeclarePairedDelimiter\floor{\lfloor}{\rfloor}
|
||||
|
||||
%\declaretheorem[within=chapter]{definition}
|
||||
%\declaretheorem[sibling=definition]{theorem}
|
||||
%\declaretheorem[sibling=definition]{corollary}
|
||||
%\declaretheorem[sibling=definition]{principle}
|
||||
|
||||
\usepackage{polyglossia}
|
||||
\usepackage[backend=biber]{biblatex}
|
||||
|
||||
\setdefaultlanguage[variant=american,ordinalmonthday=true]{english}
|
||||
|
||||
\day=7
|
||||
\month=2
|
||||
\year=2024
|
||||
|
||||
\title{Assignment 1 Report}
|
||||
\subtitle{Imperative Programming in C}
|
||||
\author{Juan Pablo Zendejas}
|
||||
\date{\today}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
%\tableofcontents
|
||||
|
||||
In this assignment, I was tasked with performing image manipulation
|
||||
using an imperative programming style in C. Using the provided PGM file,
|
||||
I wrote a program to do a threshold and rotation transformation by
|
||||
reading the image into a 2D matrix and writing the resulting 2D matrices
|
||||
to separate files.
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{minipage}{0.3\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=0.7\linewidth]{lenna.png}
|
||||
\captionof{figure}{Input file}
|
||||
\label{fig:lenna}
|
||||
\end{minipage}%
|
||||
\begin{minipage}{0.3\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=0.7\linewidth]{rotate.png}
|
||||
\captionof{figure}{Transposed}
|
||||
\label{fig:transpose}
|
||||
\end{minipage}%
|
||||
\begin{minipage}{0.3\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=0.7\linewidth]{threshold.png}
|
||||
\captionof{figure}{Threshold}
|
||||
\label{fig:thresh}
|
||||
\end{minipage}%
|
||||
\end{figure}
|
||||
|
||||
In \figref{lenna}, we see the provided input file. \figref{transpose}
|
||||
represents a transposed or rotated version of the image. Finally,
|
||||
\figref{thresh} is the image with a threshold value of 80 applied.
|
||||
Values above 80 in the 0-255 range become white while values below 80
|
||||
become black.
|
||||
|
||||
The assignment did not take too long to complete. While I was creating
|
||||
the transformation code, I ran into a segmentation fault issue when
|
||||
attempting to duplicate the matrix with the \texttt{memcpy} function.
|
||||
Eventually, I discovered that I forgot to use \texttt{malloc} on the
|
||||
rows to create the 2nd level of the 2D matrix. Once I solved that issue,
|
||||
the math was fairly simple.
|
||||
|
||||
Due to the way the rotation operation was performed using a transpose,
|
||||
rotating twice would result in the original image. Mathematically, this
|
||||
is because the transformation is the inverse of itself. Swapping $x$ and
|
||||
$y$ coordinates twice will result in the coordinates ending in the same
|
||||
order. Rotating twice would not cause the image to be upside down
|
||||
because it is not a 90° rotation, but rather a mirroring along the
|
||||
diagonal of the image.
|
||||
|
||||
I did not collaborate during this assignment. I used the UNIX
|
||||
\texttt{man} pages for documentation on the standard library and did not
|
||||
use any external library.
|
||||
|
||||
\end{document}
|
After Width: | Height: | Size: 220 KiB |
After Width: | Height: | Size: 9.7 KiB |
|
@ -0,0 +1,46 @@
|
|||
% Represents a circle.
|
||||
classdef Circle < Shape & ColorMixin
|
||||
properties
|
||||
Radius
|
||||
end
|
||||
|
||||
methods
|
||||
% The constructor takes a radius and calculates the area.
|
||||
function obj = Circle(radius)
|
||||
obj = obj@Shape("Circle")
|
||||
obj@ColorMixin("blue")
|
||||
obj.Radius = radius;
|
||||
obj.Area = obj.CalculateArea();
|
||||
end
|
||||
|
||||
% pi * r^2
|
||||
function area = CalculateArea(obj)
|
||||
obj.Area = pi * obj.Radius^2;
|
||||
area = obj.Area;
|
||||
end
|
||||
|
||||
function Display(obj)
|
||||
% Call the super method
|
||||
Display@Shape(obj)
|
||||
% Add on the radius property
|
||||
fprintf("\tRadius = %f\n", obj.Radius);
|
||||
end
|
||||
|
||||
function Draw(obj)
|
||||
Draw@Shape(obj);
|
||||
% Use a curved rectangle to draw a circle
|
||||
rectangle( ...
|
||||
'Position',[0 0 obj.Radius*2 obj.Radius*2],...
|
||||
'Curvature', [1 1], ...
|
||||
'FaceColor', obj.Color);
|
||||
% Center dot
|
||||
plot(obj.Radius, obj.Radius, '.', Color='black');
|
||||
% Radius line
|
||||
plot([obj.Radius obj.Radius*2], [obj.Radius obj.Radius]);
|
||||
% Put text denoting the radius above that line
|
||||
text(obj.Radius*1.5,obj.Radius, sprintf("r = %g", obj.Radius), HorizontalAlignment="center", VerticalAlignment="bottom");
|
||||
% Put text denoting the area
|
||||
text(obj.Radius, obj.Radius*1.5, sprintf("A = %g", obj.Area), HorizontalAlignment="center", VerticalAlignment="middle");
|
||||
end
|
||||
end
|
||||
end
|
After Width: | Height: | Size: 7.8 KiB |
|
@ -0,0 +1,23 @@
|
|||
classdef ColorMixin < handle
|
||||
properties
|
||||
Color
|
||||
end
|
||||
|
||||
methods
|
||||
function obj = ColorMixin(color)
|
||||
if nargin == 0
|
||||
obj.Color = "red";
|
||||
else
|
||||
obj.Color = color;
|
||||
end
|
||||
end
|
||||
|
||||
function color = GetColor(obj)
|
||||
color = obj.Color;
|
||||
end
|
||||
|
||||
function SetColor(obj, color)
|
||||
obj.Color = color;
|
||||
end
|
||||
end
|
||||
end
|
After Width: | Height: | Size: 8.3 KiB |
|
@ -0,0 +1,24 @@
|
|||
classdef EquilateralTriangle < Triangle & ColorMixin
|
||||
properties
|
||||
SideLength
|
||||
end
|
||||
|
||||
methods
|
||||
function obj = EquilateralTriangle(sidelength)
|
||||
obj@Triangle(sidelength, sqrt(3) * sidelength/2);
|
||||
obj@ColorMixin("cyan")
|
||||
obj.Name = "Equilateral Triangle";
|
||||
obj.SideLength = sidelength;
|
||||
end
|
||||
|
||||
function Display(obj)
|
||||
Display@Triangle(obj);
|
||||
fprintf("\tSide Length: %f units\n", obj.SideLength);
|
||||
end
|
||||
|
||||
function Draw(obj)
|
||||
Draw@Triangle(obj);
|
||||
text(cos(pi/3)*obj.SideLength/2, sin(pi/3)*obj.SideLength/2, sprintf("l = %g", obj.SideLength), HorizontalAlignment="center", VerticalAlignment="bottom", Rotation=60);
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
disp("Welcome to the Shapes script.")
|
||||
disp("Here are the following shapes you can make:")
|
||||
disp("Circle, Square, Rectangle, EquiTri, Triangle.")
|
||||
shapen = input("Which shape? ", "s");
|
||||
color = input("Color (use quotes or rgb vector)? ");
|
||||
shape = Shape("BAD SHAPE.");
|
||||
|
||||
switch (shapen)
|
||||
case "Circle"
|
||||
radius = input("Radius? ");
|
||||
shape = Circle(radius);
|
||||
case "Square"
|
||||
len = input("Side length? ");
|
||||
shape = Square(len);
|
||||
case "Rectangle"
|
||||
len = input("Length? ");
|
||||
h = input("Height? ");
|
||||
shape = Rectangle(len, h);
|
||||
case "EquiTri"
|
||||
len = input("Side Length? ");
|
||||
shape = EquilateralTriangle(len);
|
||||
case "Triangle"
|
||||
base = input("Base? ");
|
||||
height = input("Height? ");
|
||||
shape = Triangle(base, height);
|
||||
end
|
||||
|
||||
shape.SetColor(color)
|
||||
shape.Draw
|
|
@ -0,0 +1,39 @@
|
|||
classdef Rectangle < Shape & ColorMixin
|
||||
properties
|
||||
Length, Width
|
||||
end
|
||||
|
||||
methods
|
||||
function obj = Rectangle(l,w)
|
||||
obj@Shape("Rectangle")
|
||||
obj@ColorMixin("red")
|
||||
obj.Length = l;
|
||||
obj.Width = w;
|
||||
obj.Area = obj.CalculateArea;
|
||||
end
|
||||
|
||||
function area = CalculateArea(obj)
|
||||
area = obj.Length*obj.Width;
|
||||
obj.Area = area;
|
||||
end
|
||||
|
||||
function Display(obj)
|
||||
Display@Shape(obj)
|
||||
fprintf("\tLength = %f\n", obj.Length);
|
||||
fprintf("\tWidth = %f\n", obj.Width);
|
||||
end
|
||||
|
||||
function Draw(obj)
|
||||
Draw@Shape(obj);
|
||||
% Draw a rectangle
|
||||
rectangle('Position',[0 0 obj.Length obj.Width], ...
|
||||
'FaceColor', obj.Color);
|
||||
% Draw length text
|
||||
text(obj.Length / 2, 0, sprintf("l = %g", obj.Length), HorizontalAlignment="center", VerticalAlignment="bottom");
|
||||
% Draw width text
|
||||
text(obj.Length, obj.Width/2, sprintf("w = %g", obj.Width), Rotation=90, HorizontalAlignment="center", VerticalAlignment="bottom");
|
||||
% Draw area text
|
||||
text(obj.Length/2, obj.Width/2, sprintf("A = %g", obj.Area), HorizontalAlignment="center", VerticalAlignment="middle");
|
||||
end
|
||||
end
|
||||
end
|
After Width: | Height: | Size: 6.6 KiB |
|
@ -0,0 +1,43 @@
|
|||
% To let the shapes be in an array, they have to derive from the
|
||||
% Hetereogeneous mixin
|
||||
classdef Shape < ColorMixin & matlab.mixin.Heterogeneous & handle
|
||||
% These properties are shared by all Shapes.
|
||||
properties
|
||||
Name, Area
|
||||
end
|
||||
|
||||
methods
|
||||
% Base constructor to create a new shape with a specific name
|
||||
function obj = Shape(name)
|
||||
obj.Name = name;
|
||||
end
|
||||
|
||||
% Base method to display the shape in a readable format.
|
||||
function Display(obj)
|
||||
fprintf("%s shape with\n\tArea = %f square units\n\tColor = ", obj.Name, obj.Area);
|
||||
disp(obj.Color);
|
||||
end
|
||||
|
||||
% Base method that creates a figure with the title being the
|
||||
% shape's name.
|
||||
function Draw(obj)
|
||||
figure('Name',obj.Name)
|
||||
% Equal axes to preserve shape.
|
||||
axis equal
|
||||
% Prevents plot commands from resetting the figure.
|
||||
hold on
|
||||
end
|
||||
end
|
||||
|
||||
methods (Static)
|
||||
function CalculateStatistics(shapes)
|
||||
% Shapes input is an array of shape values.
|
||||
% Collect all their areas into an array.
|
||||
areas = [shapes.Area];
|
||||
% Call datastats with the column vector of all the areas.
|
||||
stats = datastats(areas(:));
|
||||
% Show output
|
||||
fprintf("Mean area: %f square units\nMedian area: %f square units\nStandard deviation: %f square units\n", stats.mean, stats.median, stats.std);
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
classdef Square < Rectangle & ColorMixin
|
||||
properties
|
||||
SideLength
|
||||
end
|
||||
|
||||
methods
|
||||
function obj = Square(sidelen)
|
||||
obj@Rectangle(sidelen, sidelen);
|
||||
obj@ColorMixin("green");
|
||||
obj.Name = "Square";
|
||||
obj.SideLength = sidelen;
|
||||
obj.Area = obj.CalculateArea;
|
||||
end
|
||||
|
||||
function Display(obj)
|
||||
Display@Shape(obj)
|
||||
fprintf("\tSide Length = %f\n", obj.SideLength);
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
classdef Triangle < Shape & ColorMixin
|
||||
properties
|
||||
Base, Height
|
||||
end
|
||||
|
||||
methods
|
||||
function obj = Triangle(base,height)
|
||||
obj@Shape("Triangle")
|
||||
obj@ColorMixin("yellow")
|
||||
obj.Base = base;
|
||||
obj.Height = height;
|
||||
obj.Area = obj.CalculateArea;
|
||||
end
|
||||
|
||||
function area = CalculateArea(obj)
|
||||
area = (obj.Base*obj.Height)/2;
|
||||
obj.Area = area;
|
||||
end
|
||||
|
||||
function Display(obj)
|
||||
Display@Shape(obj)
|
||||
fprintf("\tBase = %f units\n", obj.Base);
|
||||
fprintf("\tHeight = %f units\n", obj.Height);
|
||||
end
|
||||
|
||||
function Draw(obj)
|
||||
Draw@Shape(obj);
|
||||
ps = polyshape([0 0; obj.Base/2 obj.Height; obj.Base 0; 0 0]);
|
||||
plot(ps, FaceColor=obj.Color);
|
||||
plot([obj.Base/2 obj.Base/2],[0 obj.Height]);
|
||||
text(obj.Base/2, obj.Height/2, sprintf("h = %g", obj.Height), Rotation=90, HorizontalAlignment="center", VerticalAlignment="bottom");
|
||||
text(obj.Base/4,0,sprintf("b = %g", obj.Base), HorizontalAlignment="center", VerticalAlignment="bottom");
|
||||
text(obj.Base*(3/4),0,sprintf("A = %g", obj.Area), HorizontalAlignment="center", VerticalAlignment="bottom");
|
||||
end
|
||||
end
|
||||
end
|
After Width: | Height: | Size: 6.0 KiB |
|
@ -0,0 +1,583 @@
|
|||
%! TeX program = lualatex
|
||||
\RequirePackage[l2tabu,orthodox]{nag}
|
||||
\DocumentMetadata{lang=en-US}
|
||||
\documentclass[a4paper]{scrartcl}
|
||||
\usepackage{geometry}
|
||||
\usepackage{graphicx}
|
||||
%\usepackage{tikz}
|
||||
%\usepackage{tikz-uml}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{caption}
|
||||
\usepackage{subcaption}
|
||||
\usepackage{newfloat}
|
||||
\usepackage{fancyvrb}
|
||||
\usepackage{minted}[newfloat=true]
|
||||
\usepackage{bookmark}
|
||||
\usepackage{fontspec}
|
||||
\usepackage{microtype}
|
||||
|
||||
% Math packages
|
||||
\usepackage{amsmath}
|
||||
%\usepackage{mathtools}
|
||||
%\usepackage{amsthm}
|
||||
%\usepackage{thmtools}
|
||||
\usepackage{lualatex-math}
|
||||
\usepackage[warnings-off={mathtools-colon,mathtools-overbracket},math-style=ISO,bold-style=ISO]{unicode-math}
|
||||
|
||||
% Fonts
|
||||
\usepackage{newcomputermodern}
|
||||
\setmonofont{0xProto}[Scale=MatchLowercase]
|
||||
|
||||
\newcommand*{\figref}[2][]{%
|
||||
\hyperref[{fig:#2}]{%
|
||||
Figure~\ref*{fig:#2}%
|
||||
\ifx\\#1\\%
|
||||
\else
|
||||
\,#1%
|
||||
\fi
|
||||
}%
|
||||
}
|
||||
|
||||
\newcommand*{\lstref}[2][]{%
|
||||
\hyperref[{lst:#2}]{%
|
||||
Listing~\ref*{lst:#2}%
|
||||
\ifx\\#1\\%
|
||||
\else
|
||||
\,#1%
|
||||
\fi
|
||||
}%
|
||||
}
|
||||
|
||||
\setminted{breaklines=true,frame=single}
|
||||
\newenvironment{longlisting}{\captionsetup{type=listing}}{}
|
||||
\newenvironment{longfigure}{\captionsetup{type=figure}}{}
|
||||
\DefineVerbatimEnvironment{CommandWindow}{Verbatim}{frame=lines,
|
||||
label={Command Window}}
|
||||
\setlength{\belowcaptionskip}{10pt}
|
||||
\setlength{\abovecaptionskip}{8pt}
|
||||
%\DeclarePairedDelimiter\ceil{\lceil}{\rceil}
|
||||
%\DeclarePairedDelimiter\floor{\lfloor}{\rfloor}
|
||||
|
||||
%\declaretheorem[within=chapter]{definition}
|
||||
%\declaretheorem[sibling=definition]{theorem}
|
||||
%\declaretheorem[sibling=definition]{corollary}
|
||||
%\declaretheorem[sibling=definition]{principle}
|
||||
|
||||
\usepackage{polyglossia}
|
||||
\usepackage[backend=biber]{biblatex}
|
||||
|
||||
\setdefaultlanguage[variant=american,ordinalmonthday=true]{english}
|
||||
|
||||
\day=15
|
||||
\month=4
|
||||
\year=2024
|
||||
|
||||
\title{Programming Assignment 3}
|
||||
\subtitle{CS-420 Spring 2024}
|
||||
\author{Juan Pablo Zendejas}
|
||||
\date{\today}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
%\listoftheorems[ignoreall,onlynamed={theorem,corollary,principle}]
|
||||
%\listoftheorems[ignoreall,onlynamed={definition},title={List of Definitions}]
|
||||
%\tableofcontents
|
||||
|
||||
\section{Introduction}
|
||||
|
||||
For this assignment, I was tasked with implementing object-oriented
|
||||
programming principles in the MATLAB language. This includes inheritance
|
||||
in single, multiple, and multi-level forms. I also had to practice the
|
||||
concept of calling super-class methods and overriding methods. This
|
||||
involved creating a group of classes that represented different shapes,
|
||||
and implementing methods and providing properties for these classes.
|
||||
|
||||
\section{Task One: Class Creation and Constructors}
|
||||
|
||||
My first task was to create a base class called \texttt{Shape}. It holds
|
||||
properties \texttt{Name} and \texttt{Area}, a constructor to set the
|
||||
name, and a \texttt{Display} method. The code is displayed in
|
||||
\lstref{shape}.
|
||||
|
||||
Originally, it consisted of just the properties, the constructor, and
|
||||
the \texttt{Display} method. The other methods were added in the next
|
||||
tasks and will be discussed then. The output for the task is given in
|
||||
\figref{taskone}.
|
||||
|
||||
\begin{longfigure}
|
||||
\begin{CommandWindow}
|
||||
>> shape1 = Shape("Timmy")
|
||||
|
||||
shape1 =
|
||||
|
||||
Shape with properties:
|
||||
|
||||
Name: "Timmy"
|
||||
Area: []
|
||||
Color: "red"
|
||||
|
||||
>> shape2 = Shape("Jimmy")
|
||||
|
||||
shape2 =
|
||||
|
||||
Shape with properties:
|
||||
|
||||
Name: "Jimmy"
|
||||
Area: []
|
||||
Color: "red"
|
||||
|
||||
>> shape1.Display
|
||||
Timmy shape with
|
||||
Area = square units
|
||||
Color = red
|
||||
>> shape2.Display
|
||||
Jimmy shape with
|
||||
Area = square units
|
||||
Color = red
|
||||
>>
|
||||
\end{CommandWindow}
|
||||
\caption{Output from testing Task 1.}
|
||||
\label{fig:taskone}
|
||||
\end{longfigure}
|
||||
|
||||
\section{Task Two: Inheritance and Constructor Overloading}
|
||||
|
||||
This task involved creating new classes that derived from Shape, calling
|
||||
the super constructor to set the name. The code listings for the 3 classes are
|
||||
shown in \lstref{circle}, \lstref{rectangle}, and \lstref{triangle}.
|
||||
|
||||
|
||||
|
||||
When I started this task, it was a bit difficult at first to figure out
|
||||
how MATLAB's class inheritance works. A lot of MATLAB syntax is very
|
||||
different to me coming from other languages. Eventually, I figured out
|
||||
that you need to use the \texttt{<} less than symbol and the
|
||||
\texttt{\&}
|
||||
ampersand to define inheritance with the \texttt{classdef}.
|
||||
|
||||
All of the three constructors call the \texttt{Shape} constructor using
|
||||
the \texttt{@}-sign notation. This was another strange thing to me
|
||||
coming from other languages, and I'm still getting used to it. In
|
||||
MATLAB, the super-constructor calls have to come first and can't be in
|
||||
conditionals. However, all I needed it to do was set the shape name, so
|
||||
that wasn't a problem here.
|
||||
|
||||
Finally, I had to add a \texttt{CalculateArea} method to all of the
|
||||
classes. This method would calculate the area of the shape and save it
|
||||
to the \texttt{Area} property on the object. While attempting to
|
||||
implement this method, I found out that by default MATLAB classes are
|
||||
passed by value. This was annoying because the area wasn't being saved
|
||||
by the CalculateArea class and I couldn't figure out why. Eventually, I
|
||||
found out that to get behavior like which I'm used to from other
|
||||
languages, \texttt{Shape} had to derive from the \texttt{handle} class
|
||||
built-in to MATLAB. Deriving the \texttt{handle} class, as shown in
|
||||
\lstref{shape} on line 3, makes the class' instances pass by reference
|
||||
instead of by value. Then, assigning class properties became easy.
|
||||
|
||||
This \texttt{CalculateArea} method was called in the constructor to
|
||||
assign the correct value right after the object was constructed. See
|
||||
\figref{tasktwo} for the command window output and testing.
|
||||
|
||||
\begin{longfigure}
|
||||
\begin{CommandWindow}
|
||||
>> rect1 = Rectangle(5,6)
|
||||
|
||||
rect1 =
|
||||
|
||||
Rectangle with properties:
|
||||
|
||||
Length: 5
|
||||
Width: 6
|
||||
Name: "Rectangle"
|
||||
Area: 30
|
||||
Color: "red"
|
||||
|
||||
>> rect2 = Rectangle(6,7)
|
||||
|
||||
rect2 =
|
||||
|
||||
Rectangle with properties:
|
||||
|
||||
Length: 6
|
||||
Width: 7
|
||||
Name: "Rectangle"
|
||||
Area: 42
|
||||
Color: "red"
|
||||
|
||||
>> tri1 = Triangle(5,6)
|
||||
|
||||
tri1 =
|
||||
|
||||
Triangle with properties:
|
||||
|
||||
Base: 5
|
||||
Height: 6
|
||||
Name: "Triangle"
|
||||
Area: 15
|
||||
Color: "yellow"
|
||||
|
||||
>> tri2 = Triangle(2,7)
|
||||
|
||||
tri2 =
|
||||
|
||||
Triangle with properties:
|
||||
|
||||
Base: 2
|
||||
Height: 7
|
||||
Name: "Triangle"
|
||||
Area: 7
|
||||
Color: "yellow"
|
||||
|
||||
>> circ1 = Circle(5)
|
||||
|
||||
circ1 =
|
||||
|
||||
Circle with properties:
|
||||
|
||||
Radius: 5
|
||||
Name: "Circle"
|
||||
Area: 78.5398
|
||||
Color: "blue"
|
||||
|
||||
>> circ2 = Circle(10)
|
||||
|
||||
circ2 =
|
||||
|
||||
Circle with properties:
|
||||
|
||||
Radius: 10
|
||||
Name: "Circle"
|
||||
Area: 314.1593
|
||||
Color: "blue"
|
||||
\end{CommandWindow}
|
||||
\caption{Testing for Task Two.}
|
||||
\label{fig:tasktwo}
|
||||
\end{longfigure}
|
||||
|
||||
\section{Task Three: Method Overriding}
|
||||
|
||||
In this task, I wrote the \texttt{Display} methods for the
|
||||
\texttt{Circle}, \texttt{Rectangle}, and \texttt{Triangle} class. These
|
||||
methods override the original \texttt{Display} method defined in
|
||||
\texttt{Shape}, and are shown in the corresponding listings
|
||||
\lstref{circle}, \lstref{rectangle}, and \lstref{triangle}.
|
||||
|
||||
To make the implementation more consistent, I created them as an
|
||||
extension of the \texttt{Shape}'s \texttt{Display} method. I had to
|
||||
figure out the syntax for calling super methods in MATLAB, which was
|
||||
very similar to the method of calling super constructors. Thus, I had to
|
||||
write \texttt{Display@Shape(obj)} to first call the super method. Then,
|
||||
I used more \texttt{fprintf} function calls to add on appropriate
|
||||
information for the class. The test output is shown in
|
||||
\figref{taskthree}.
|
||||
|
||||
\begin{longfigure}
|
||||
\begin{CommandWindow}
|
||||
>> rect1.Display
|
||||
Rectangle shape with
|
||||
Area = 30.000000 square units
|
||||
Color = red
|
||||
Length = 5.000000
|
||||
Width = 6.000000
|
||||
>> circ1.Display
|
||||
Circle shape with
|
||||
Area = 78.539816 square units
|
||||
Color = blue
|
||||
Radius = 5.000000
|
||||
>> tri1.Display
|
||||
Triangle shape with
|
||||
Area = 15.000000 square units
|
||||
Color = yellow
|
||||
Base = 5.000000 units
|
||||
Height = 6.000000 units
|
||||
\end{CommandWindow}
|
||||
\caption{Test output for Task 3.}
|
||||
\label{fig:taskthree}
|
||||
\end{longfigure}
|
||||
|
||||
\section{Task Four: Multi-Level Inheritance}
|
||||
|
||||
Multi-level inheritance is when you create a subclass of a subclass,
|
||||
which increases the level of separation and grouping. For our Shapes, I
|
||||
had to create classes that represent an Equilateral Triangle and a
|
||||
Square. Thus, they would derive from \texttt{Triangle} and
|
||||
\texttt{Rectangle} respectively. The code for these classes is shown in
|
||||
\lstref{equitri} and \lstref{square}.
|
||||
|
||||
In these classes, the constructor called their respective super class
|
||||
constructor, with appropriate properties calculated from the given
|
||||
value. Thus, the area would be properly assigned. All that was left was
|
||||
to change the name. While I would have simply called the \texttt{Shape}
|
||||
constructor, it was already in use by the super class. And, as explained
|
||||
in the static method section, it would have caused issues with the later
|
||||
implementation. Thus, I decided to simply overwrite it with an
|
||||
assignment for these classes.
|
||||
|
||||
I did not have to override the \texttt{CalculateArea} method since the
|
||||
calculation method is the same for the derived shapes. However, I did
|
||||
override the \texttt{Display} method, calling the super-class version
|
||||
and adding on the specialized properties. The test output is shown in
|
||||
\figref{taskfour}.
|
||||
|
||||
\begin{longfigure}
|
||||
\begin{CommandWindow}
|
||||
>> eqtri1 = EquilateralTriangle(5);
|
||||
>> sq1 = Square(4);
|
||||
>> eqtri1.Display
|
||||
Equilateral Triangle shape with
|
||||
Area = 10.825318 square units
|
||||
Color = cyan
|
||||
Base = 5.000000 units
|
||||
Height = 4.330127 units
|
||||
Side Length: 5.000000 units
|
||||
>> sq1.Display
|
||||
Square shape with
|
||||
Area = 16.000000 square units
|
||||
Color = green
|
||||
Side Length = 4.000000
|
||||
\end{CommandWindow}
|
||||
\caption{Test output for Task 4.}
|
||||
\label{fig:taskfour}
|
||||
\end{longfigure}
|
||||
|
||||
\section{Task Five: Multiple Inheritance}
|
||||
|
||||
Multiple inheritance differs from multi-level inheritance, as multiple
|
||||
inheritance is when one class derives from multiple super-classes. For
|
||||
this task, I had to create a new class called \texttt{ColorMixin} that
|
||||
simply defined a new property, \texttt{Color}, and some methods to
|
||||
change it. The class is shown in \lstref{color}. As I fixed bugs, it
|
||||
turned out that all classes on an object had to be \texttt{handle}s, so
|
||||
I had to make \texttt{ColorMixin} derive from that class.
|
||||
|
||||
Also, I had to make \texttt{ColorMixin} have a default color value. This
|
||||
was achieved by reading the MATLAB documentation, and using the
|
||||
\texttt{nargin} variable. This variable contains the number of arguments
|
||||
given to the function. When it's 0, I simply set \texttt{Color} to be
|
||||
red by default.
|
||||
|
||||
In addition, I discovered that MATLAB colors can either be a string or a
|
||||
vector of RGB values. So, the set and get color methods have no
|
||||
restriction on the type of the parameter.
|
||||
|
||||
Finally, I had to make all the shapes derive from the
|
||||
\texttt{ColorMixin} class so I could use its constructor in the shape
|
||||
constructors. Each shape has a different default color based on what I
|
||||
feel that shape's color is. The test output for this task is shown in
|
||||
\figref{taskfive}.
|
||||
|
||||
\begin{longfigure}
|
||||
\begin{CommandWindow}
|
||||
>> circ1.Display
|
||||
Circle shape with
|
||||
Area = 78.539816 square units
|
||||
Color = red
|
||||
Radius = 5.000000
|
||||
>> circ1.SetColor("blue")
|
||||
>> tri1.Display
|
||||
Triangle shape with
|
||||
Area = 15.000000 square units
|
||||
Color = yellow
|
||||
Base = 5.000000 units
|
||||
Height = 6.000000 units
|
||||
>> tri1.SetColor([0.5 0.3 0.9])
|
||||
>> tri1.Display
|
||||
Triangle shape with
|
||||
Area = 15.000000 square units
|
||||
Color = 0.5000 0.3000 0.9000
|
||||
|
||||
Base = 5.000000 units
|
||||
Height = 6.000000 units
|
||||
\end{CommandWindow}
|
||||
\caption{Test output for Task 5.}
|
||||
\label{fig:taskfive}
|
||||
\end{longfigure}
|
||||
|
||||
\section{Task Six: Static Method}
|
||||
|
||||
This task involves creating a static method to determine some statistics
|
||||
about a list of shapes' area values. To achieve this, the \texttt{Shape}
|
||||
class has to derive from the \texttt{Heterogeneous} mixin, in order
|
||||
for heterogeneous arrays of shapes to be created. This also adds the
|
||||
restriction that classes can only derive from one heterogeneous class;
|
||||
which is why Equilateral Triangle and Square could not also derive from
|
||||
Shape.
|
||||
|
||||
To implement this method, I used the MATLAB \texttt{datastats} method,
|
||||
which returns a dictionary containing some common statistic parameters.
|
||||
In particular, we're looking at the mean, median, and standard
|
||||
deviation. Look at \lstref{shape} to see the implementation. In essence,
|
||||
I can use the vectorization properties of MATLAB to use the common
|
||||
``parameter get'' dot notation, which actually collects the
|
||||
\texttt{Area} property of all the shapes in the array. I then collect it
|
||||
into another array by wrapping it in square brackets.
|
||||
|
||||
Finally, to collect the array into a column vector that
|
||||
\texttt{datastats} requires, I use the spread operator \texttt{(:)} with
|
||||
null parameters to get the entire array in a column vector.
|
||||
\texttt{datastats} will calculate the statistics, which are then printed
|
||||
out. An example is shown in \figref{tasksix}.
|
||||
|
||||
\begin{longfigure}
|
||||
\begin{CommandWindow}[breaklines=true]
|
||||
>> shapes = [Triangle(4,5), Circle(5), Rectangle(4,5), EquilateralTriangle(6), Square(10)]
|
||||
|
||||
shapes =
|
||||
|
||||
1x5 heterogeneous Shape (Triangle, Circle, Rectangle, ...) array with properties:
|
||||
|
||||
Name
|
||||
Area
|
||||
Color
|
||||
|
||||
>> Shape.CalculateStatistics(shapes)
|
||||
Mean area: 44.825655 square units
|
||||
Median area: 20.000000 square units
|
||||
Standard deviation: 41.427063 square units
|
||||
\end{CommandWindow}
|
||||
\caption{Test output for Task 6.}
|
||||
\label{fig:tasksix}
|
||||
\end{longfigure}
|
||||
|
||||
\section{Task Seven: Visualization}
|
||||
|
||||
For this task, I had to use MATLAB's built-in visualization methods to
|
||||
create a \texttt{Draw} method that displays a figure representing the
|
||||
shape. I achieved this primarily using the \texttt{plot}, \texttt{text},
|
||||
and \texttt{rectangle} functions included in MATLAB.
|
||||
|
||||
I first created a base \texttt{Draw} method in the \texttt{Shape} class.
|
||||
By reading the documentation, I found out that I could use the
|
||||
\texttt{figure} function to start a new figure and give it a name, which
|
||||
I set to the shape's name. To preserve the outline of the shape, I used
|
||||
\texttt{axis equal}, and to prevent future \texttt{plot} calls from
|
||||
changing the options, I used \texttt{hold on}.
|
||||
|
||||
For the circle in \lstref{circle}, I used a call to \texttt{rectangle}
|
||||
with a curvature of 1. I added some lines to draw a point and a line,
|
||||
then some text for the area and radius.
|
||||
|
||||
For the triangle, I used the \texttt{polyshape} method I found in some
|
||||
documentation examples. I passed it a matrix of coordinates that defined
|
||||
the points of the shape, and then used the \texttt{plot} command to fill
|
||||
it in. Finally, I added some text and lines to represent the base,
|
||||
height, and area. The equilateral triangle class uses the triangle draw
|
||||
method, but adds the side length as text on the figure.
|
||||
|
||||
For the rectangle, I just used the \texttt{rectangle} method to fill in
|
||||
the shape. Then, I had 3 calls to \texttt{text} to add length, width,
|
||||
and area. The square doesn't add anything new to the figure.
|
||||
|
||||
Some example figures are shown in \figref{circle}, \figref{triangle},
|
||||
\figref{equitri}, and \figref{rectangle}.
|
||||
|
||||
\begin{figure}[!hbt]
|
||||
\centering
|
||||
\subcaptionbox{A circle.\label{fig:circle}}[.475\linewidth]
|
||||
{\includegraphics[width=\linewidth]{Circle.png}}\hfill %
|
||||
\subcaptionbox{A triangle.\label{fig:triangle}}[.475\linewidth]
|
||||
{\includegraphics[width=\linewidth]{Triangle.png}}
|
||||
|
||||
\medskip
|
||||
|
||||
\subcaptionbox{An equilateral triangle.\label{fig:equitri}}[.475\linewidth]
|
||||
{\includegraphics[width=\linewidth]{EquiTri.png}}\hfill %
|
||||
\subcaptionbox{A rectangle.\label{fig:rectangle}}[.475\linewidth]
|
||||
{\includegraphics[width=\linewidth]{Rectangle.png}}
|
||||
|
||||
\caption{Shapes as generated by MATLAB.}
|
||||
\label{fig:shapes}
|
||||
\end{figure}
|
||||
|
||||
\section{Task Eight: User Interaction}
|
||||
|
||||
The final task was to create an interactive script that lets a user
|
||||
create a shape and type out the parameters. This code is shown in
|
||||
\lstref{script}. The script is fairly simple. I use the \texttt{input}
|
||||
method of MATLAB to ask for a name of a shape. I need the \texttt{"s"}
|
||||
operator to get a simple string. However, for the color and for the
|
||||
parameter inputs, I don't use that so the user can input an expression,
|
||||
or for the color, a vector of RGB values. An example of its use is found
|
||||
in \figref{script}. At the end, a window opens showing the shape as
|
||||
found in \figref{shapes}.
|
||||
|
||||
\begin{longfigure}
|
||||
\begin{CommandWindow}
|
||||
>> MyShapes
|
||||
Welcome to the Shapes script.
|
||||
Here are the following shapes you can make:
|
||||
Circle, Square, Rectangle, EquiTri, Triangle.
|
||||
Which shape?
|
||||
Circle
|
||||
Color (use quotes or rgb vector)?
|
||||
[0.9 0.4 0.2]
|
||||
Radius?
|
||||
10
|
||||
\end{CommandWindow}
|
||||
\caption{Output of MyShapes script.}
|
||||
\label{fig:script}
|
||||
\end{longfigure}
|
||||
|
||||
\section{Conclusion}
|
||||
|
||||
This was certainly an interesting project. To be honest, the PDF given
|
||||
was a little confusing with the instructions, but I believe I was able
|
||||
to learn all that I needed about MATLAB's standard library and its uses.
|
||||
I had a lot of fun making this document look nice and pretty, especially
|
||||
\figref{shapes} which took a bit of digging. Also, the MATLAB
|
||||
documentation is immense but easy to search through and has plenty of
|
||||
examples.
|
||||
|
||||
\section{Source Code}
|
||||
|
||||
\begin{longlisting}
|
||||
\inputminted[label={Shape.m}]{matlab}{Shape.m}
|
||||
\caption[Shape.m]{Shape class.}
|
||||
\label{lst:shape}
|
||||
\end{longlisting}
|
||||
|
||||
\begin{longlisting}
|
||||
\inputminted[label={Circle.m}]{matlab}{Circle.m}
|
||||
\caption[Circle.m]{Circle class.}
|
||||
\label{lst:circle}
|
||||
\end{longlisting}
|
||||
|
||||
\begin{longlisting}
|
||||
\inputminted[label={Rectangle.m}]{matlab}{Rectangle.m}
|
||||
\caption[Rectangle.m]{Rectangle class.}
|
||||
\label{lst:rectangle}
|
||||
\end{longlisting}
|
||||
|
||||
\begin{longlisting}
|
||||
\inputminted[label={Triangle.m}]{matlab}{Triangle.m}
|
||||
\caption[Triangle.m]{Triangle class.}
|
||||
\label{lst:triangle}
|
||||
\end{longlisting}
|
||||
|
||||
\begin{longlisting}
|
||||
\inputminted[label={EquilateralTriangle.m}]{matlab}{EquilateralTriangle.m}
|
||||
\caption[EquilateralTriangle.m]{EquilateralTriangle class.}
|
||||
\label{lst:equitri}
|
||||
\end{longlisting}
|
||||
|
||||
\begin{longlisting}
|
||||
\inputminted[label={Square.m}]{matlab}{Square.m}
|
||||
\caption[Square.m]{Square class.}
|
||||
\label{lst:square}
|
||||
\end{longlisting}
|
||||
|
||||
\begin{longlisting}
|
||||
\inputminted[label={ColorMixin.m}]{matlab}{ColorMixin.m}
|
||||
\caption[ColorMixin.m]{ColorMixin class.}
|
||||
\label{lst:color}
|
||||
\end{longlisting}
|
||||
|
||||
\begin{longlisting}
|
||||
\inputminted[label={MyShapes.m}]{matlab}{MyShapes.m}
|
||||
\caption[MyShapes.m]{MyShapes script.}
|
||||
\label{lst:script}
|
||||
\end{longlisting}
|
||||
|
||||
\end{document}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
:- style_check(-singleton).
|
||||
% DO NOT MODIFY
|
||||
|
||||
:- consult('ReadCSV.pl').
|
||||
:- use_module(library(date)).
|
||||
:- read_csv_and_store('EmployeeData.csv').
|
||||
|
||||
% DO NOT MODIFY
|
||||
|
||||
is_seattle_employee(Name) :- person(_, Name, _, _, _, _, _, _, _, _, _, _, 'Seattle',_).
|
||||
|
||||
is_senior_manager_in_IT(Name) :- person(_, Name, 'Sr. Manger', 'IT', _, _, _, _, _, _, _, _, _, _).
|
||||
|
||||
is_director_finance_miami(Name) :- person(_, Name, 'Director', 'Finance', _, _, _, _, _, _, _, _, 'Miami', _).
|
||||
|
||||
is_asian_US_manufacturing_40M(Name, Unit, Gender, Ethnicity, Age) :- person(_, Name, _, _, Unit, Gender, Ethnicity, Age, _, _, _, _, _, _), Age > 40, Unit = 'Manufacturing', Gender = 'Male', Ethnicity = 'Asian'.
|
||||
|
||||
% format calls write internally
|
||||
greet(EEID) :- person(EEID, Name, Job, Dept, Unit, _, _, _, _, _, _, _, _, _), format('Hello, ~w, ~w, ~w, ~w!~n', [Name, Job, Dept, Unit]).
|
||||
|
||||
years_until_retirement(Name, Age, Until) :- person(_, Name, _, _, _, _, _, Age, _, _, _, _, _, _), Until is 65-Age.
|
||||
|
||||
is_rd_black_midAge(Name, Unit, Ethnicity, Age) :- person(_, Name, _, _, Unit, _, Ethnicity, Age, _, _, _, _, _, _), Ethnicity = 'Black', Unit = 'Research & Development', Age >= 25, Age =< 50.
|
||||
|
||||
is_ITorFin_PHXorMIAorAUS(Name, Dept, City) :- person(_, Name, _, Dept, _, _, _, _, _, _, _, _, City, _),
|
||||
(Dept = 'IT'; Dept = 'Finance'),
|
||||
(City = 'Phoenix'; City = 'Miami'; City = 'Austin').
|
||||
|
||||
is_female_senior_role(Name, Title) :- person(_, Name, Title,_,_,'Female',_,_,_,_,_,_,_,_), atom_concat('Sr.', _, Title).
|
||||
|
||||
% Helper predicate that converts a salary string to a number
|
||||
% Remove $.
|
||||
convert_salary(In, Out) :- atom_concat('$', NoDollar, In),
|
||||
% Split by commas, and additionally remove trailing whitespace
|
||||
split_string(NoDollar, ',', '\t\s', NoCommaList),
|
||||
% Concatenate the list back into an atom.
|
||||
atomic_list_concat(NoCommaList, SalaryAtom),
|
||||
% Convert the atom into a number.
|
||||
atom_number(SalaryAtom, Out).
|
||||
|
||||
is_highly_paid_senior_manager(Name, Salary) :- person(_, Name, 'Sr. Manger', _, _, _, _, _, _, Salary, _, _, _, _),
|
||||
convert_salary(Salary, SalaryN),
|
||||
SalaryN > 120000.
|
||||
|
||||
% Divisibility test
|
||||
divides(N,X) :- 0 is X mod N.
|
||||
|
||||
% prime/2 is helper predicate.
|
||||
% it is a recursive algorithm that tests all the numbers from N up to x,
|
||||
% ensuring they all do not divide N.
|
||||
% Base case.
|
||||
prime(N, N) :- true, !.
|
||||
% X should not divide N, and the next number also should not.
|
||||
prime(X, N) :- not(divides(X, N)), Next is X+1, prime(Next, N).
|
||||
|
||||
% prime/1 calls prime/2.
|
||||
prime(N) :- prime(2,N).
|
||||
|
||||
is_prime_age(Name, Age) :- person(_, Name, _, _, _, _, _, Age, _, _, _, _, _, _), prime(Age).
|
||||
|
||||
% Uses convert_salary.
|
||||
total_salary(Name, Salary) :- person(_, Name, _, _, _, _, _, _, _, AnnSal, BonusP, _, _, _),
|
||||
convert_salary(AnnSal, AnnSalN), atom_concat(Bonus, '%', BonusP), atom_number(Bonus, BonusN),
|
||||
Salary is AnnSalN + (AnnSalN * (BonusN / 100)).
|
||||
|
||||
takehome_salary(Name, Title, Salary) :- person(_, Name, Title,_,_,_,_,_,_,_,_,_,_,_),
|
||||
% Get the total salary.
|
||||
total_salary(Name, AS),
|
||||
% Semicolon causes backtracking.
|
||||
(
|
||||
% "One of these clauses should be true"
|
||||
AS =< 50000, Tax = 20/100;
|
||||
AS > 50000, AS =< 100000, Tax = 25/100;
|
||||
AS > 100000, AS =< 200000, Tax = 30/100;
|
||||
AS > 200000, Tax = 35/100
|
||||
% Unified value for Tax is then used here.
|
||||
), Salary is AS - (AS * Tax).
|
||||
|
||||
total_years(Name, Years) :- person(_,Name,_,_,_,_,_,_,Hire,_,_,_,_,Exit),
|
||||
% parse timestamp to get the year number
|
||||
split_string(Hire, '/', '', [_,_,HireYrS]),
|
||||
atom_number(HireYrS, HireYrShort),
|
||||
% since it's a short number, add 1900 if > 50
|
||||
% but otherwise add 2000
|
||||
(HireYrShort < 50, HireYr is HireYrShort + 2000;
|
||||
HireYr is HireYrShort + 1900),
|
||||
% find "exit" year
|
||||
(Exit = '', get_time(T), stamp_date_time(T, DT, local), date_time_value(year, DT, CurYear), Years is CurYear - HireYr, !;
|
||||
% parse exit year
|
||||
split_string(Exit, '/', '', [_,_,ExitYrS]),
|
||||
atom_number(ExitYrS, ExitYrShort),
|
||||
(ExitYrShort < 50, ExitYr is ExitYrShort + 2000;
|
||||
ExitYr is ExitYrShort + 1900),
|
||||
Years is ExitYr - HireYr, !).
|
||||
|
||||
|
||||
title_salary(Title, Salary) :- person(_,_,Title,_,_,_,_,_,_,SalaryS,_,_,_,_), convert_salary(SalaryS, Salary).
|
||||
|
||||
% bagof() gets al the possible salaries for a title. Then, i use foldl
|
||||
% to sum up all of the salaries, and divide by the number of salaries,
|
||||
% which is the formula for the average.
|
||||
average_salary(Title, AvgSalary) :- bagof(Salary, title_salary(Title, Salary), SalList), foldl(plus, SalList, 0, Total), length(SalList, N), AvgSalary is Total / N.
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
:- use_module(library(csv)).
|
||||
|
||||
% Predicate to read data from a CSV file and store it as rules
|
||||
read_csv_and_store(Filename) :-
|
||||
csv_read_file(Filename, [_|Rows], []),
|
||||
process_rows(Rows).
|
||||
|
||||
% Process each row in the CSV file and store data as rules
|
||||
process_rows([]).
|
||||
process_rows([Row|Rows]) :-
|
||||
process_row(Row),
|
||||
process_rows(Rows).
|
||||
|
||||
% Store data from a row as a rule
|
||||
process_row(row(EEID, Name, Job, Department, Unit, Gender, Ethnicity, Age, Hired, Salary, Bonus, Country, City, Exited)) :-
|
||||
assert(person(EEID, Name, Job, Department, Unit, Gender, Ethnicity, Age, Hired, Salary, Bonus, Country, City, Exited)).
|
||||
|
|
@ -0,0 +1,343 @@
|
|||
%! TeX program = lualatex
|
||||
\RequirePackage[l2tabu,orthodox]{nag}
|
||||
\DocumentMetadata{lang=en-US}
|
||||
\documentclass[a4paper]{scrartcl}
|
||||
\usepackage{geometry}
|
||||
\usepackage{graphicx}
|
||||
%\usepackage{tikz}
|
||||
%\usepackage{tikz-uml}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{caption}
|
||||
\usepackage{subcaption}
|
||||
\usepackage{newfloat}
|
||||
\usepackage{fancyvrb}
|
||||
\usepackage{minted}[newfloat=true]
|
||||
\usepackage{bookmark}
|
||||
\usepackage{fontspec}
|
||||
\usepackage{microtype}
|
||||
|
||||
% Math packages
|
||||
%\usepackage{amsmath}
|
||||
%\usepackage{mathtools}
|
||||
%\usepackage{amsthm}
|
||||
%\usepackage{thmtools}
|
||||
%\usepackage{lualatex-math}
|
||||
%\usepackage[warnings-off={mathtools-colon,mathtools-overbracket},math-style=ISO,bold-style=ISO]{unicode-math}
|
||||
|
||||
% Fonts
|
||||
\usepackage{newcomputermodern}
|
||||
\setmonofont{0xProto}[Scale=MatchLowercase]
|
||||
|
||||
\newcommand*{\figref}[2][]{%
|
||||
\hyperref[{fig:#2}]{%
|
||||
Figure~\ref*{fig:#2}%
|
||||
\ifx\\#1\\%
|
||||
\else
|
||||
\,#1%
|
||||
\fi
|
||||
}%
|
||||
}
|
||||
|
||||
\newcommand*{\lstref}[2][]{%
|
||||
\hyperref[{lst:#2}]{%
|
||||
Listing~\ref*{lst:#2}%
|
||||
\ifx\\#1\\%
|
||||
\else
|
||||
\,#1%
|
||||
\fi
|
||||
}%
|
||||
}
|
||||
|
||||
|
||||
\setminted{breaklines=true,frame=single,linenos=true}
|
||||
\newenvironment{longlisting}{\captionsetup{type=listing}}{}
|
||||
\newenvironment{longfigure}{\captionsetup{type=figure}}{}
|
||||
\setlength{\belowcaptionskip}{10pt}
|
||||
\setlength{\abovecaptionskip}{8pt}
|
||||
%\DeclarePairedDelimiter\ceil{\lceil}{\rceil}
|
||||
%\DeclarePairedDelimiter\floor{\lfloor}{\rfloor}
|
||||
|
||||
%\declaretheorem[within=chapter]{definition}
|
||||
%\declaretheorem[sibling=definition]{theorem}
|
||||
%\declaretheorem[sibling=definition]{corollary}
|
||||
%\declaretheorem[sibling=definition]{principle}
|
||||
|
||||
\usepackage{polyglossia}
|
||||
\usepackage[backend=biber]{biblatex}
|
||||
|
||||
\setdefaultlanguage[variant=american,ordinalmonthday=true]{english}
|
||||
|
||||
\day=3
|
||||
\month=5
|
||||
\year=2024
|
||||
|
||||
\title{Logical Programming in Prolog}
|
||||
\subtitle{Assignment 4}
|
||||
\author{Juan Pablo Zendejas}
|
||||
\date{\today}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
%\listoftheorems[ignoreall,onlynamed={theorem,corollary,principle}]
|
||||
%\listoftheorems[ignoreall,onlynamed={definition},title={List of Definitions}]
|
||||
%\tableofcontents
|
||||
|
||||
In this assignment, I was tasked with creating Prolog predicates that
|
||||
query the database of employees given in a CSV file. I created 15 rules
|
||||
as specified in the assignment PDF. Overall, this assignment was very
|
||||
interesting to me. Prolog is very different from any other programming
|
||||
language I've used, even Haskell. Getting used to the eccentricities of
|
||||
SWI-Prolog and reading its documentation gave me a lot of insight. In
|
||||
addition, my background of formal logic from Discrete Mathematics taken
|
||||
here at SDSU gave me a lot of parallels that helped me understand how to
|
||||
write code.
|
||||
|
||||
I did not receive any external help except from consulting the SWI
|
||||
Prolog handbook/documentation found on their website. This documentation
|
||||
was very useful to figure out what predicates to use to transform some
|
||||
of the data.
|
||||
|
||||
\section{CSV File Importing}
|
||||
|
||||
First I had to change the \texttt{ReadCSV.pl} file to import all the
|
||||
rows from the CSV, ignoring the first title row. The source code is
|
||||
displayed in \lstref{readcsv}.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={ReadCSV.pl}]{prolog}{ReadCSV.pl}
|
||||
\caption{CSV reader.}
|
||||
\label{lst:readcsv}
|
||||
\end{listing}
|
||||
|
||||
This part wasn't too bad. I simply had to ignore the first row, which I
|
||||
did by using Pattern Matching on the \texttt{csv\_read\_file} predicate to
|
||||
ignore the first entry of the list and simply take the tail as the
|
||||
\texttt{Rows} variable.
|
||||
|
||||
Then, on \texttt{process\_row}, I simply filled in the \texttt{assert}
|
||||
call with all the names of the columns.
|
||||
|
||||
\section{Writing Rules}
|
||||
|
||||
Now, I was tasked with using the imported facts from the CSV and writing
|
||||
rules that would be used as queries to the dataset.
|
||||
|
||||
\subsection{Rule One}
|
||||
Simple rule, displayed in \lstref{seattleempl}. The \texttt{:-} symbol
|
||||
is reminiscent of ``yields'' from mathematics. I use the underscore to
|
||||
discard the variables from the \texttt{people} predicate that I don't
|
||||
need, and just check if a person exists with that name and is from
|
||||
Seattle.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={is\_seattle\_employee},firstline=10,lastline=10]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine if an employee is from Seattle.}
|
||||
\label{lst:seattleempl}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Two}
|
||||
Very similar to rule one, displayed in \lstref{seniormangerit}. Now, we
|
||||
just have more filters to apply, which is done by replacing some of the
|
||||
underscores with concrete values.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={is\_senior\_manager\_in\_it},firstline=12,lastline=12]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine if an employee is a senior manager in IT.}
|
||||
\label{lst:seniormangerit}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Three}
|
||||
Displayed in \lstref{rule3}. Standard like the previous rules.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={is\_director\_finance\_miami},firstline=14,lastline=14]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine if an employee is a Director of Finance
|
||||
in Miami.}
|
||||
\label{lst:rule3}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Four}
|
||||
This rule is a little more complicated. It's displayed in
|
||||
\lstref{rule4}. Since this predicate has more arguments, I have them
|
||||
directly wired into the \texttt{person} predicate. Then, I simply have
|
||||
conditions that specify the values of those predicates. In addition, I
|
||||
had to do this for \texttt{Age} because I need to check if it's greater
|
||||
than 40.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={is\_asian\_US\_manufacturing\_40M},firstline=16,lastline=16]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine if an employee is a 40 or older Asian
|
||||
male working in manufacturing in the US.}
|
||||
\label{lst:rule4}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Five}
|
||||
This rule is given an employee ID, and should print a greeting for that
|
||||
employee. The source code is displayed in \lstref{rule5}. I looked in
|
||||
the SWI-Prolog documentation to figure out how to format a string, and I
|
||||
found the \texttt{format/2} predicate. It basically uses the ~ symbol to
|
||||
define placeholders. Then, using the \texttt{person} predicate to get
|
||||
the data from the employee ID and outputting it with \texttt{format/2}
|
||||
was pretty easy.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={greet},firstline=19,lastline=19]{prolog}{Assign4.pl}
|
||||
\caption{Rule to greet an employee from their ID.}
|
||||
\label{lst:rule5}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Six}
|
||||
This rule calculates an employee's number of years until retirement. The
|
||||
retirement age is given as 65. This was fairly simple, I had to use the
|
||||
\texttt{is} operator to calculate a value and unify it with the
|
||||
predicate's argument. The source code is displayed in \lstref{rule6}.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={years\_until\_retirement},firstline=21,lastline=21]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine an employee's years until retirement.}
|
||||
\label{lst:rule6}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Seven}
|
||||
This rule is similar to the previous ones, but now I define two
|
||||
conditions on the age, using the less than and greater than operators.
|
||||
Prolog is interesting in this regard because it has the order of the
|
||||
symbols swapped from what it usually is. Something to remember for sure.
|
||||
The source code is displayed in \lstref{rule7}.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={is\_rd\_black\_midAge},firstline=23,lastline=23]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine if an employee is middle-aged, black, and
|
||||
in research and development.}
|
||||
\label{lst:rule7}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Eight}
|
||||
This rule introduced me to the semicolon operator, and how to use it to
|
||||
make more complicated rules. Basically, the semicolon operator tells
|
||||
Prolog to backtrack and try other possibilities if one of the dependent
|
||||
propositions is false. I can wrap stuff in parentheses and use the
|
||||
semicolon to define ``or''-like statements. The source code is displayed in
|
||||
\lstref{rule8}.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={is\_ITorFin\_PHXorMIAorAUS},firstline=25,lastline=27]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine if an employee is in IT or finance, and
|
||||
in Phoenix or Miami or Austin.}
|
||||
\label{lst:rule8}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Nine}
|
||||
This rule introduced me to the \texttt{atom\_concat} predicate. It was
|
||||
really interesting to learn that in Prolog, predicates like these can
|
||||
work in different ways based on which variable needs to be unified.
|
||||
Thus, even though the predicate is called \texttt{concat}, it can also
|
||||
split. That's what I did here to remove the `Sr.' from the employee's
|
||||
title. The predicate is only true (can be unified) when the title starts
|
||||
with Sr. The source code is displayed in \lstref{rule9}.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={is\_female\_senior\_role},firstline=29,lastline=29]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine if an employee is both female and in a
|
||||
senior role.}
|
||||
\label{lst:rule9}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Ten}
|
||||
For this rule, I had to create a helper predicate
|
||||
\texttt{convert\_salary/2}, which is shown in \lstref{convertsalary}.
|
||||
Now, I had to write predicates that reasoned with numbers instead of
|
||||
just atom equality. The source code is shown in \lstref{rule10}. This
|
||||
can be done with typical symbols like less than, greater than. I also
|
||||
have to write code to convert the string representation of the salary
|
||||
into a number; this was done by first removing the dollar sign, then
|
||||
removing the comma and parsing it into a number. The SWI Prolog
|
||||
documentation helped here.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={convert\_salary},firstline=33,lastline=39]{prolog}{Assign4.pl}
|
||||
\caption{Rule to convert a salary string to a number.}
|
||||
\label{lst:convertsalary}
|
||||
\end{listing}
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={is\_highly\_paid\_senior\_manager},firstline=41,lastline=43]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine if an employee is a highly paid senior
|
||||
manager.}
|
||||
\label{lst:rule10}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Eleven}
|
||||
This rule determines if an employee has an age that's prime. This one
|
||||
was difficult. I thought I could use an algorithm similar to Haskell,
|
||||
but that was a generator. I ended up using a naive recursive algorithm
|
||||
that checks if all the numbers less than the age do NOT divide the age.
|
||||
Probably inefficient, but it works. The source code is shown in
|
||||
\lstref{rule11}.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={is\_prime\_age},firstline=45,lastline=59]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine if an employee has a prime age.}
|
||||
\label{lst:rule11}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Twelve}
|
||||
This rule calculates an employee's salary after bonuses, but before
|
||||
taxes. Now that I wrote \texttt{convert\_salary/2}, this predicate has a
|
||||
fairly simple and easy to read implementation. It is displayed in
|
||||
\lstref{rule12}.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={total\_salary},firstline=62,lastline=64]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine an employee's total salary.}
|
||||
\label{lst:rule12}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Thirteen}
|
||||
Now, this rule calculates the take-home salary of an employee. This is
|
||||
done by using a tax bracketed system based on the employee's total
|
||||
salary. Again, I had to use the semicolon to provide backtracking and
|
||||
alternatives for Prolog, which worked as a conditional to set the tax
|
||||
level. The code is displayed in \lstref{rule13}.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={takehome\_salary},firstline=66,lastline=77]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine an employee's take-home salary.}
|
||||
\label{lst:rule13}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Fourteen}
|
||||
This was a pretty complicated predicate to write, but it was fun. The
|
||||
source code is displayed in \lstref{rule14}. I used the SWI-Prolog
|
||||
documentation to figure out how to use the date-time objects and
|
||||
predicates. One of the difficult parts is the strange date format in the
|
||||
CSV, which I had to parse using \texttt{split\_string/4} and some pattern
|
||||
matching. Then, I had to convert the short year number into a year in
|
||||
the 20th or 21st century.
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={total\_years},firstline=79,lastline=94]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine an employee's years of service.}
|
||||
\label{lst:rule14}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Rule Fifteen}
|
||||
Finally, I had to write a rule to determine the average salary for an
|
||||
entire job title. The source code is displayed in \lstref{rule15}.
|
||||
Using the ways of Prolog backtracking, this actually
|
||||
wasn't too bad. Essentially, I wrote a predicate that simply gets the
|
||||
salary for a specific person with a title. There are many ways to unify
|
||||
the Salary variable that make the predicate true. Then, I use the Prolog
|
||||
\texttt{bagof/3} predicate to collect every possible value that
|
||||
satisfies the predicate into a list. Then, getting the average is easy.
|
||||
|
||||
|
||||
\begin{listing}
|
||||
\inputminted[label={average\_salary},firstline=97,lastline=102]{prolog}{Assign4.pl}
|
||||
\caption{Rule to determine the average salary for a job title.}
|
||||
\label{lst:rule15}
|
||||
\end{listing}
|
||||
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,11 @@
|
|||
parent(john, mary).
|
||||
parent(john, tom).
|
||||
parent(mary, lisa).
|
||||
parent(tom, jerry).
|
||||
|
||||
male(john).
|
||||
male(tom).
|
||||
male(jerry).
|
||||
female(mary).
|
||||
female(lisa).
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
eats(elephant, shrub).
|
||||
eats(tiger, deer).
|
||||
eats(lion, zebra).
|
||||
eats(panda, bamboo).
|
||||
eats(cow, grass).
|
||||
|
||||
plant(shrub).
|
||||
plant(bamboo).
|
||||
plant(grass).
|
||||
|
||||
meat(deer).
|
||||
meat(zebra).
|
||||
|
||||
herbivore(X) :- eats(X, Y), plant(Y).
|
||||
|
||||
carnivore(X) :- eats(X, Y), meat(Y).
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
take(0, _, []).
|
||||
take(_, [], []).
|
||||
take(Count, [F|Rest], List) :- Next is Count-1, List = [F | Part], take(Next, Rest, Part).
|
||||
|
||||
member(X, [C|Rest]) :- X = C; member(X, Rest).
|
||||
|
|
@ -6,4 +6,3 @@ fibs :: [Int]
|
|||
-- F_n+2 = 1 + sum(F_1 .. F_n)
|
||||
fibs = 1 : scanl (+) 1 fibs
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
import System.IO
|
||||
import Data.List( delete )
|
||||
-- A definition for zipWith:
|
||||
|
||||
zipWith' :: (a->b->c) -> [a] -> [b] -> [c]
|
||||
zipWith' f (x:xs) (y:ys) = f x y : zipWith' (f) xs ys
|
||||
zipWith' _ _ _ = []
|
||||
|
||||
-- Solution for fibs:
|
||||
|
||||
-- 0 1 2 3 5 8
|
||||
-- 1 2 3 5 8
|
||||
-- ^ one off, so we zipWith (+) with the list and the tail half of the
|
||||
-- list.
|
||||
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
|
||||
|
||||
-- An example of an impure IO function.
|
||||
act :: IO (Char, Char)
|
||||
act = do x <- getChar
|
||||
getChar
|
||||
y <- getChar
|
||||
return (x,y)
|
||||
|
||||
-- How to get a line
|
||||
getLine' :: IO String
|
||||
getLine' = do x <- getChar
|
||||
if x == '\n' then
|
||||
return []
|
||||
else
|
||||
do xs <- getLine'
|
||||
return (x:xs)
|
||||
|
||||
-- How to put a String
|
||||
putStr' :: String -> IO ()
|
||||
putStr' [] = return ()
|
||||
putStr' (x:xs) = do putChar x
|
||||
putStr' xs
|
||||
|
||||
putStrLn' :: String -> IO ()
|
||||
putStrLn' xs = do putStr' xs
|
||||
putChar '\n'
|
||||
|
||||
-- Now, an example of an interactive program
|
||||
strlen :: IO ()
|
||||
strlen = do putStr "Enter a string: "
|
||||
xs <- getLine
|
||||
putStr "The string has "
|
||||
putStr (show (length xs))
|
||||
putStrLn " characters."
|
||||
|
||||
-- how to do a hangman game?
|
||||
|
||||
getCh :: IO Char
|
||||
getCh = do hSetEcho stdin False
|
||||
x <- getChar
|
||||
hSetEcho stdin True
|
||||
return x
|
||||
|
||||
sgetLine :: IO String
|
||||
sgetLine = do x <- getCh
|
||||
if x == '\n' then
|
||||
do putChar x
|
||||
return []
|
||||
else
|
||||
do putChar '-'
|
||||
xs <- sgetLine
|
||||
return (x:xs)
|
||||
|
||||
replace xs i r =
|
||||
|
||||
match :: String -> String -> String
|
||||
match _ [] = []
|
||||
match word@(w:ws) (x:xs) = if w == x then '!' : match ws xs
|
||||
else if elem x word then
|
||||
'?' : match (delete x word) xs
|
||||
else '-' : match word xs
|
||||
|
||||
--match word guess = [if g == w then '!' else if elem g word then '?' else '-' | (w,g) <- zip word guess]
|
||||
|
||||
play :: String -> Int -> IO ()
|
||||
play word 0 = do putStr "Out of guesses... The word was "
|
||||
putStrLn word
|
||||
play word guesses = do putStr "? "
|
||||
guess <- getLine
|
||||
if guess == word then
|
||||
putStrLn "You got it!"
|
||||
else
|
||||
do putStrLn (match word guess)
|
||||
play word (guesses - 1)
|
||||
|
||||
|
||||
hangman :: IO ()
|
||||
hangman = do putStr "Think of a word: "
|
||||
word <- sgetLine
|
||||
putStrLn "Try to guess it:"
|
||||
play word 6
|
|
@ -0,0 +1,8 @@
|
|||
-- Backtracking
|
||||
|
||||
|
||||
minCost :: [Int] -> Int
|
||||
minCost [] = 0
|
||||
minCost (_:[]) = 0
|
||||
minCost (x:y:xs) = min x y + minCost xs
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
data Tree a = Leaf | Branch a (Tree a) (Tree a)
|
||||
|
||||
leftside :: Tree a -> a
|
||||
leftside (Branch x Leaf _) = x
|
||||
leftside (Branch _ a _) = leftside a
|