Pete Metcalfe posted: " Matlab has been an extremely popular tool for Engineering and Mathematical problem solving. Matlab has a wide range of practical applications and use-cases. It is also used in complex industrial applications such as multi-variable control in chemical rea"
Matlab has been an extremely popular tool for Engineering and Mathematical problem solving. Matlab has a wide range of practical applications and use-cases. It is also used in complex industrial applications such as multi-variable control in chemical reactors.
Matlab is a full featured commercial product that has a perpetual license for $2,150 US (or $860 yearly). Student pricing, (starting at $49 US, add-ons extras ), home pricing ($149 US, add-ons extra) and 30 day trials are available for non-commercial projects.
Octave is an open source alternative to Matlab that runs on GNU/Linux, macOS, BSD, and Microsoft Windows. The Octave syntax is largely compatible with Matlab.
I wish I had known about Octave when I was trying to help my kids with their high school Algebra and Calculus homework. In this blog I was look at introducing Octave with some high school math questions. I will finish with a quick data analysis example and a sensor example.
Getting Started with Octave
Octave/Matlab has a lot of potential applications and it can be loaded on a standard PC for math/stats projects or on a Raspberry Pi for projects that use GPIO (General Purpose Inputs and Outputs) to connect to sensors and I/O devices.
# load the base Octave software sudo apt-get install octave # add some of the key Octave packages sudo apt-get install octave-control octave-image octave-io octave-optim octave-signal octave-statistics
The Octave Forge site (https://octave.sourceforge.io/packages.php ) has a list of useful community based libraries that can be added. To load a custom library, first install any dependencies then use the Octave pkg (package) command to install and load new library. For example to load the Symbolic library:
$ # install package dependencies $ pip3 install sympy==1.5.1 $ octave octave:1> # install symbolic package from forge site octave:1> pkg install -forge symbolic octave:2> # make package available by loading octave:2> pkg load symbolic octave:3> # show installed and loaded (*) packages octave:3> pkg list Package Name | Version | Installation directory --------------+---------+----------------------- control | 3.2.0 | /usr/share/octave/packages/control-3.2.0 dataframe | 1.2.0 | /home/pete/octave/dataframe-1.2.0 image | 2.12.0 | /usr/share/octave/packages/image-2.12.0 io | 2.4.13 | /usr/share/octave/packages/io-2.4.13 optim | 1.6.0 | /usr/share/octave/packages/optim-1.6.0 signal | 1.4.1 | /usr/share/octave/packages/signal-1.4.1 statistics | 1.4.1 | /usr/share/octave/packages/statistics-1.4.1 struct | 1.0.16 | /usr/share/octave/packages/struct-1.0.16 symbolic *| 2.9.0 | /home/pete/octave/symbolic-2.9.0
Solve Quadratic Equations
The power of Octave or Matlab can shown in it's handling of Algebraic equations.
A typical high school math question would be to find where 2 equations intersect. Below is an example to solve where:
2*x^2 - 8*x - 4 = 3*x -x^2
Some comments on Octave/Matlab syntax, an exponent is define by: ".^" , and a "==" denotes that symbolic equation1 = equation2. A single "=" sets a variable to a value. If a line ends in ";" the lines results are hidden, otherwise the lines results are shown. The Octave prompt can be simplified by the command: PS1(">> #") .
>> #Solve for the intercept between 2 equations >> pkg load symbolic >> syms x >> eq1 = 2*x.^2 - 8*x - 4 == 3*x -x.^2 eq1 = (sym) 2 2 2⋅x - 8⋅x - 4 = - x + 3⋅x >> solve(eq1) ans = (sym 2×1 matrix) ⎡-1/3⎤ ⎢ ⎥ ⎣ 4 ⎦ >> # Show the number numerically >> double(ans) ans = -0.33333 4.0 >># Plot the first equation >> ezplot(@(x) 2*x.^2 - 8*x - 4 ) >> # Use "hold on" so the first plot isn't erased >> hold on; >> ezplot(@(x) 3*x -x.^2 ) >> title ('2*x.^2 - 8*x - 4 = 3*x -x.^2')
Balance Chemical Equations
An example of balancing chemical equations, would be to determine how much methane (CH4 ) and oxygen (O2) would burn cleanly to water(H20) and carbon dioxide (CO2):
CH4 + O2 → CO2 + H2O
To determine the actual amounts of each element variables X1-X4 are added:
Now there are 3 equations and 4 variable. To solved these equations, as a first pass x4=1 (now there are 4 equations). The 4 equation can be defined in a matrix equation of : Ax = b:
To solve this in Octave/Matlab the matrices are A and b are defined then the equation is rearranged to:
x = A-1 *b
>> # Balance equation of: Methane + Oxygen -> Carbon Dioxide + Water >> # Create a Matrix A of elements >> A = [ 1 0 -1 0 4 0 0 -2 0 2 -2 -1 0 0 0 1]; >> # Create a Matric b of results >> b = [ 0 0 0 1]; >> # Ax = b, or x=inverse(A) * b, solve for x >> x = inv(A) *b x = 0.50000 1.00000 0.50000 1.00000 >> # Multiple by 2 to get whole numbers >> x = 2*x x = 1 2 1 2
Originally a guess of x4 = 1 was used, this gave a result with decimal/fractional values. By setting X4 = 2 (multiple results by 2) whole values can returned. The final balanced equation is:
CH4 + 2O2 → CO2 + 2H2O
Dataframes
An Octave dataframe (similar to a Python Pandas dataframe) is used to store rows and columns of data.
Dataframes can be used to filter, sort and do stats on data files.
CSV files can be imported into dataframe objects. I found that for some files the dataframe import failed, as a work around I imported the CSV file first into a csv2cell object.
Below is an example of imported a CSV file and showing the first 6 rows in a bar chart:
>> pkg load dataframe >> c = csv2cell("buildings.csv"); >> df = dataframe(c); >> # show the first 3 rows and all the columns >> df(1:3, : ) ans = dataframe with 3 rows and 6 columns _1 rank name height theyear city country Nr double char double double char char 1 1 Burj Khalifa 2717 2010 Dubai United Arab Emirates 2 2 Merdeka 118 2227 2022 Kuala Lumpur Malaysia 3 3 Shanghai Tower 2073 2015 Shanghai China >> >> # create a bar chart with the first 6 tallest buildings, show height and name >> bar(df(1:6,['height']) ) >> set(gca,'XTickLabel',df(1:6,['name'])
Dataframes can filtered based on conditions with a field. Below is an example of the tallest building in the US that was built after 2014:
>> us = df(strcmp(cellstr(df.country),'United States') & df.theyear > 2014, : ) us = dataframe with 6 rows and 6 columns _1 rank name height theyear city country Nr double char double double char char 15 15 Central Park Tower 1550 2020 New York City United States 28 28 111 West 57th Street 1428 2021 New York City United States 29 29 One Vanderbilt 1401 2020 New York City United States 31 31 432 Park Avenue 1397 2015 New York City United States 45 45 30 Hudson Yards 1270 2019 New York City United States 64 64 St. Regis Chicago 1191 2020 Chicago United States
Statistical functions can also be used with filters.
>> # Find the tallest building built up until 2000 >> max(df.height(df.theyear <= 2000)) ans = 1483
Data Sensor Example
Octave has a number of libraries that allow for sensor inputs from Arduino, Raspberry Pi modules and hardware interfaces such as serial, TCP sockets and I2C devices. The data can then be analysed and outputed to SQL databases, CSV files, plots, dialogs and Excel files.
For the last example a script will periodically read a sensor value then:
save times/values to a CSV file
show the last 20 values in a dynamic plot
show a dialog with a moving average of the last 5 values.
The Octave script (sensor1.m) is launched at the command line by: octave sensor1.m .
For this example the sensor value is simulated by using the CPU idle time that is returned from the top utility. The zenity library is loaded and used for the moving average dialog.
There are a number of way to export data to a CSV file. This example uses a simple bash echo with the results piped to sensor1.csv .
#!/usr/bin/octave # # sensor1.m - scan a simulated sensor, then graph and save values # pkg load zenity cmd = "top -n 1 | grep %Cpu | awk '{printf $8}'"; p = zenity_progress("Sensor Value "); # Cycle for 1000 iterations x = []; for i = 1:1000 # get the sensor (idletime) value and time thetime = strftime("%X",localtime (time ())); [~, idletime] = system(cmd); idletime_n = str2num(idletime); x(end+1) = idletime_n; # Only graph the last 20 values if length(x) > 20 x(1) = []; endif plot(x) title(strcat("Sensor Values Last Value: ", idletime, "%")) # Show a move average of the last 5 points in a dialog pause (2); if length(x) > 5 movavg = mean(x(end-5:end)); the_comment = strcat(idletime, " % (Ave of last 5 samples"); zenity_progress(p,the_comment,movavg); endif # append the time and sensor value to a text file outcmd = ["echo " thetime " , " idletime " >> sensor1.csv"]; system(outcmd); endfor
Final Comments
For a high school or university student who needs to do some mathematical or engineer work and doesn't have access to Matlab, Octave is a great open source alternative.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.