<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://griffinhurt.com/feed.xml" rel="self" type="application/atom+xml"/><link href="https://griffinhurt.com/" rel="alternate" type="text/html" hreflang="en"/><updated>2026-03-23T18:22:18+00:00</updated><id>https://griffinhurt.com/feed.xml</id><title type="html">blank</title><subtitle>Griffin Hurt is a computer science Ph.D. student at the University of Pittsburgh. </subtitle><entry><title type="html">Stereo Matching and Depth Map Creation on the Vision Pro</title><link href="https://griffinhurt.com/blog/2025/avp-stereo/" rel="alternate" type="text/html" title="Stereo Matching and Depth Map Creation on the Vision Pro"/><published>2025-06-13T05:00:00+00:00</published><updated>2025-06-13T05:00:00+00:00</updated><id>https://griffinhurt.com/blog/2025/avp-stereo</id><content type="html" xml:base="https://griffinhurt.com/blog/2025/avp-stereo/"><![CDATA[<p><em>TLDR: I implemented Stereo Matching on the Vision Pro using RAFT-Stereo and visionOS 26! <a href="https://github.com/surreality-lab/VisionProDisparityMatching">Source code is here!</a></em></p> <p>With the recent release of visionOS 26 at WWDC 2025, Apple has finally <a href="https://developer.apple.com/videos/play/wwdc2025/223/">given developers access to the right camera on the Vision Pro</a> (<em>at least, developers with an enterprise license</em>). This greatly expands the capability of the Vision Pro for environment understanding and registration by enabling depth to be calculated from a rectified stereo pair (see <a href="https://en.wikipedia.org/wiki/Binocular_vision">binocular vision</a> and <a href="https://en.wikipedia.org/wiki/Epipolar_geometry">epipolar geometry</a>). These last few days, I’ve been trying to put together a reasonable pipeline for stereo matching and, ergo, depth map calculation on the Vision Pro. While calculating depth still eludes me, I at least have a reasonable pipeline for disparity estimation on the Vision Pro.</p> <p><em>(Note: I’m going to use the Swift version of <code class="language-plaintext highlighter-rouge">ARKit</code> throughout this article so that the syntax is a bit easier to follow. There’s also a <a href="https://developer.apple.com/documentation/arkit/arkit-in-visionos-c-api">C API</a> that might be more useful for developers building in support to existing libraries.)</em></p> <h2 id="getting-frames-from-the-main-camera-on-the-apple-vision-pro">Getting Frames from the Main Camera on the Apple Vision Pro</h2> <p>The first step to doing any type of depth or disparity calculation on the Vision Pro is to get camera frames from both the left and right cameras using the <code class="language-plaintext highlighter-rouge">ARKit</code> API. The <a href="https://developer.apple.com/documentation/visionos/accessing-the-main-camera">“Accessing The Main Camera” Xcode project</a> from Apple provides a good codebase to start from, but I’ll briefly explain the process here as well.</p> <p>In <code class="language-plaintext highlighter-rouge">ARKit</code>, you can instantiate a session (<a href="https://developer.apple.com/documentation/arkit/arkitsession"><code class="language-plaintext highlighter-rouge">ARKitSession</code></a>) that consists of multiple providers (<a href="https://developer.apple.com/documentation/arkit/dataprovider"><code class="language-plaintext highlighter-rouge">DataProvider</code></a>), each delivering some type of AR data to the application. A basic example would be a <a href="https://developer.apple.com/documentation/arkit/worldtrackingprovider"><code class="language-plaintext highlighter-rouge">WorldTrackingProvider</code></a> that provides information about the device pose and “anchors” in the user’s surroundings (I would imagine this is what Unity is using under the hood to position the XR camera). When you want to access camera data, you instantiate a <a href="https://developer.apple.com/documentation/arkit/cameraframeprovider"><code class="language-plaintext highlighter-rouge">CameraFrameProvider</code></a> and add it to your <code class="language-plaintext highlighter-rouge">ARKitSession</code> in <code class="language-plaintext highlighter-rouge">session.run([cameraFrameProvider, &lt;whatever other providers you need&gt;])</code>. After you start the session with your frame provider (ensuring that the frame provider is supported with <code class="language-plaintext highlighter-rouge">CameraFrameProvider.isSupported</code>), you listen to frames by creating an async for loop over <a href="https://developer.apple.com/documentation/arkit/cameraframeprovider/cameraframeupdates(for:)"><code class="language-plaintext highlighter-rouge">cameraFrameProvider.cameraFrameUpdates(for: someFormat)</code></a>, where <code class="language-plaintext highlighter-rouge">someFormat</code> is a format picked from <code class="language-plaintext highlighter-rouge">CameraVideoFormat.supportedVideoFormats</code>. In visionOS 26, you have access to <a href="https://developer.apple.com/documentation/arkit/cameraframeprovider/camerarectification"><code class="language-plaintext highlighter-rouge">CameraFrameProvider.CameraRectification</code></a>, so make sure you pick a video format that’s stereo rectified. This eliminates the need for a library like OpenCV to <a href="https://en.wikipedia.org/wiki/Image_rectification">stereo rectify</a> the left and right image feeds (in technical terms, aligning the <a href="https://en.wikipedia.org/wiki/Epipolar_geometry#Epipolar_line">epipolar lines</a> to be horizontal).</p> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/pixel_formats-480.webp 480w,/assets/img/pixel_formats-800.webp 800w,/assets/img/pixel_formats-1400.webp 1400w," sizes="95vw" type="image/webp"/> <img src="/assets/img/pixel_formats.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> <p><small>Figre 1: Some examples of pixel formats available on the Vision Pro. The 864 x 704 pixel, <code class="language-plaintext highlighter-rouge">stereoCorrected</code> format is probably the most useful for this tutorial. Pixel formats are in <a href="https://en.wikipedia.org/wiki/FourCC">FourCC</a> format, so when you see “875704422”, it’s just the int32 representation of “420f” (YUV 4:2:0 chroma subsampling or <a href="https://developer.apple.com/documentation/corevideo/kcvpixelformattype_420ypcbcr8biplanarfullrange">kCVPixelFormatType_420YpCbCr8BiPlanarFullRange</a>).</small></p> <p>Once you have your main loop, you can access “samples” (a bundle containing the image, camera intrinsics, and camera extrinsics) from the left and right cameras using <code class="language-plaintext highlighter-rouge">cameraFrame.sample(for: .left)</code> and <code class="language-plaintext highlighter-rouge">cameraFrame.sample(for: .right)</code> (the latter is new in visionOS 26). You can access the image from a sample as a <code class="language-plaintext highlighter-rouge">CVPixelBuffer</code> through <code class="language-plaintext highlighter-rouge">sample.pixelBuffer</code> (Xcode 26 will yell at you for this, since <a href="https://developer.apple.com/documentation/CoreVideo/cvpixelbuffer-q2e"><code class="language-plaintext highlighter-rouge">CVPixelBuffer</code></a> is deprecated and being replaced with <a href="https://developer.apple.com/documentation/corevideo/cvbuffer-nfm"><code class="language-plaintext highlighter-rouge">CVBuffer</code></a> despite its lack of support in other frameworks… <em>foreshadowing</em>). Now that we have the images, we have to figure out a way to calculate disparity per pixel so that we can calculate depth.</p> <h2 id="calculating-disparity-from-a-stereo-pair">Calculating Disparity from a Stereo Pair</h2> <p><a href="https://en.wikipedia.org/wiki/Binocular_disparity">Disparity</a> refers to the distance a pixel travels along the x axis between the left and right camera in a stereo pair. In a stereo rectified image, (once again, an image in which epipolar lines are all horizontal), disparity is also the distance a pixel travels along its epipolar line, which has a lot of importance for calculating depth. The relationship between depth and disparity is inversely proportional (assuming the same <a href="https://en.wikipedia.org/wiki/Pinhole_camera_principal_point">principal point</a> in both cameras):</p> \[\text{depth} = \frac{\text{focal length} \times \text{baseline}}{\text{disparity}}\] <p>I spend a lot of time thinking about ways to convert stereo pairs of images to disparity maps, as it’s an important first step in photogrammetry and stereo reconstruction. There are a multitude of options for this problem including classical approaches (<a href="https://docs.opencv.org/3.4/d9/dba/classcv_1_1StereoBM.html"><code class="language-plaintext highlighter-rouge">StereoBM</code></a> and <a href="https://docs.opencv.org/4.x/d2/d85/classcv_1_1StereoSGBM.html"><code class="language-plaintext highlighter-rouge">StereoSGBM</code></a> in OpenCV, <a href="https://wildboar-dev.github.io/PatchMatch/">PatchMatch stereo</a>, etc.), ML approaches (the cutting edge <a href="https://nvlabs.github.io/FoundationStereo/">FoundationStereo</a>, <a href="https://research.google/pubs/stereonet-guided-hierarchical-refinement-for-edge-aware-depth-prediction/">StereoNet</a> from Google, <a href="https://arxiv.org/abs/2109.07547">RAFT-Stereo</a>, etc.), and even combined approaches (<a href="https://arxiv.org/abs/2012.01411">PatchMatchNet</a>). <code class="language-plaintext highlighter-rouge">StereoBM</code> is often the first choice of developers due to its integration with OpenCV and fast computation, but I find it leaves a lot to be desired in user experience (you have to spend a lot of time tuning the parameters) and pixel density. I chose to implement <a href="https://github.com/princeton-vl/RAFT-Stereo">RAFT-Stereo</a> for this experiment due to its relatively fast inference time (~45ms on neural cores) and comparatively dense estimation. There’s even a <a href="https://openaccess.thecvf.com/content/WACV2024/papers/Cheng_Stereo_Matching_in_Time_100_FPS_Video_Stereo_Matching_for_WACV_2024_paper.pdf">paper that expands RAFT-Stereo to 100+ FPS</a> by warm-starting the model on previous frames, but there’s no PyTorch implementation, so this remains as an exercise for future work.</p> <h2 id="bundling-raft-stereo-for-vision-pro">Bundling RAFT-Stereo for Vision Pro</h2> <p>In today’s world, there’s so many ways to run a machine learning model on embedded hardware. The option that I like the most (and that I wish had more widespread adoption) is <a href="https://onnx.ai/">ONNX</a> (Open Neural Network eXchange), but interoperability sometimes begets inefficiency, and I realized that my only option was going to be a pure <a href="https://developer.apple.com/documentation/coreml/">CoreML</a> model to leverage the Neural Cores on the Vision Pro. <em>(Yes, ONNX has a <a href="https://onnxruntime.ai/docs/execution-providers/CoreML-ExecutionProvider.html">CoreML backend</a>, but CoreML tools dropped support for ONNX a while back and operation types like <a href="https://onnx.ai/onnx/operators/onnx__GridSample.html"><code class="language-plaintext highlighter-rouge">GridSample</code></a> don’t seem to have support for conversion…)</em></p> <p>So, I set out to convert the RAFT-Stereo PyTorch implementation to a CoreML model using <a href="https://apple.github.io/coremltools/docs-guides/"><code class="language-plaintext highlighter-rouge">coremltools</code></a>. Unfortunately, naïve conversion of the real-time model (specifically using <code class="language-plaintext highlighter-rouge">torch.jit.trace</code>) did not work due to a 7 dimension tensor in the <a href="https://github.com/princeton-vl/RAFT-Stereo/blob/main/core/raft_stereo.py#L55C9-L55C22"><code class="language-plaintext highlighter-rouge">upsample_flow</code></a> function because CoreML only supports 5D tensors (<code class="language-plaintext highlighter-rouge">torch.export.export</code> didn’t work either because the model was in the <code class="language-plaintext highlighter-rouge">TRAINING</code> dialect even though I put the model in <code class="language-plaintext highlighter-rouge">eval</code> mode…). The 7D tensor gets passed through a softmax layer, so I took great care in ensuring model functionality was preserved when reshaping. After solving that issue (and switching <code class="language-plaintext highlighter-rouge">corr_implementation</code> to <code class="language-plaintext highlighter-rouge">reg</code> instead of <code class="language-plaintext highlighter-rouge">alt</code>), the <code class="language-plaintext highlighter-rouge">torch.jit.trace</code> method for conversion worked like a charm, and I was able to save the model to a <code class="language-plaintext highlighter-rouge">.mlpackage</code> (specifically on 512x512 color images).</p> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/raft_stereo_out-480.webp 480w,/assets/img/raft_stereo_out-800.webp 800w,/assets/img/raft_stereo_out-1400.webp 1400w," sizes="95vw" type="image/webp"/> <img src="/assets/img/raft_stereo_out.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> <p><small>Figure 2: Example output from my RAFT-Stereo CoreML model run on 512x512 images. The underlying stereo image was taken from a spatial video captured on Vision Pro.</small></p> <p><em>Note: I know <a href="https://github.com/pytorch/executorch">ExecuTorch</a> is designed to simplify situations exactly like this, but for some reason I couldn’t get the Swift package to work with visionOS. The xcframeworks compiled just fine with the <a href="https://github.com/leetal/ios-cmake">iOS CMake toolchain</a>, but the Swift package wouldn’t cooperate. (Also the XNNPACK backend wouldn’t build for some reason…)</em></p> <h2 id="testing-the-raft-stereo-coreml-model">Testing the RAFT-Stereo CoreML Model</h2> <p>After I was able to produce the RAFT-Stereo CoreML model, I wanted to make sure that I was able to run it somewhat efficiently on hardware. Some basic tests with <code class="language-plaintext highlighter-rouge">coremltools</code> in Python (see Figure 2) validated that the output was consistent with what I would expect, so I knew that the model was working properly at a mechanical level at least. Running some performance reports on my Mac indicated that most of the network modules were running on neural cores and that the median inference time was around 45ms, which sounded fantastic to me. Unfortunately, it appears that the neural cores on the Vision Pro are not quite as robust: performance tests on device showed that the majority of modules were running on GPU with a median inference time of around 135ms. I came to learn that this is due to some 32-bit float (FP32) weights sticking around in the model. I tried my best to fix this by turning off the <code class="language-plaintext highlighter-rouge">mixed_precision</code> flag in the model and exporting the CoreML model with <code class="language-plaintext highlighter-rouge">compute_precision=coremltools.precision.FLOAT16</code>, but nothing seemed to fix it. Perhaps quantizing the model with PyTorch before tracing would be more productive. Either way, the model was within a reasonable margin of latency for me, and I wanted to implement a full pipeline with camera capture and the model to get disparity maps on the Vision Pro.</p> <h2 id="putting-it-all-together">Putting it All Together</h2> <p>I started by duplicating the “Accessing the Main Camera” demo project from Apple and adding my <code class="language-plaintext highlighter-rouge">Enterprise.license</code> file. A breaking change in Enterprise API main camera access that doesn’t seem to be documented anywhere is that <code class="language-plaintext highlighter-rouge">NSMainCameraUsageDescription</code> has replaced <code class="language-plaintext highlighter-rouge">NSEnterpriseMCAMUsageDescription</code> in <code class="language-plaintext highlighter-rouge">Info.plist</code>, so make sure you add a usage description under that key. <em>(Also be sure you install the Metal toolchain for visionOS 26 because sometimes it doesn’t install by default and your application fails silently to a runtime error. Ask me how I know!)</em></p> <p>Once the basic application was running (and after checking the <code class="language-plaintext highlighter-rouge">.right</code> camera sample was available), I started modifying the code to rescale and crop the left and right <code class="language-plaintext highlighter-rouge">CVPixelBuffer</code> objects to 512x512 for model inference. (I used my local LLM for help at this point since <code class="language-plaintext highlighter-rouge">CoreVideo</code> and <code class="language-plaintext highlighter-rouge">CoreImage</code> can sometimes trip me up.) After verifying that the buffers were scaled down to 512x512, I tried to import the model by dragging the <code class="language-plaintext highlighter-rouge">.mlpackage</code> into my Xcode project. The default initializer in the automatically generated Swift class for the model caused the runtime error “<code class="language-plaintext highlighter-rouge">error: ANE cannot handle intermediate tensor type fp32</code>”, which I figured was related to the mixed precision issue I saw in my model tests. To get around this, I simply passed a <a href="https://developer.apple.com/documentation/coreml/mlmodelconfiguration"><code class="language-plaintext highlighter-rouge">MLModelConfiguration</code></a> with <code class="language-plaintext highlighter-rouge">computeUnits</code> set to <code class="language-plaintext highlighter-rouge">.cpuAndGPU</code> in the initialization function and the error went away.</p> <p>After that, all I had to do was implement a function that converted the <a href="https://developer.apple.com/documentation/coreml/mlmultiarray"><code class="language-plaintext highlighter-rouge">MLMultiArray</code></a> that came out of my CoreML model to a <code class="language-plaintext highlighter-rouge">CVPixelBuffer</code> for presentation, and boom! I was able to get a ~9fps feed of disparity calculation on the Vision Pro!</p> <figure> <video src="/assets/video/Stereo3.mp4" class="img-fluid rounded z-depth-1" width="auto" height="auto" autoplay="" controls=""/> </figure> <p><em>Note: Yes, I know <code class="language-plaintext highlighter-rouge">CVPixelBuffer</code> is deprecated in visionOS 26. Unfortunately, it appears the CoreML API has not been updated to accept <code class="language-plaintext highlighter-rouge">CVBuffer</code> objects yet, so I have to stick with <code class="language-plaintext highlighter-rouge">CVPixelBuffer</code> objects in the meantime.</em></p> <h2 id="the-future-and-mistakes-made">The Future and Mistakes Made</h2> <p>The obvious next step for stereo matching on the AVP is to convert the disparity map to a depth map via the standard equation and then produce a point cloud using the camera intrinsics. I’m working on an implementation that uses <code class="language-plaintext highlighter-rouge">Accelerate.framework</code> to speed up the vector operations and sends the results to Unity after computation, but the extrinsics calculations and interop are still confusing to me.</p> <p>Of course, my implementation is inefficient in some areas. The most obvious area of improvement is in the CoreML model. If I could get it to be entirely FP16, I could utilize the neural cores and hopefully get the inference time back into the ~50ms range; I just haven’t figured it out yet. Additionally, my implementation of <code class="language-plaintext highlighter-rouge">multiArrayToRGBA</code> is almost certainly inefficient given that I’m performing the conversion in a big for loop (the <code class="language-plaintext highlighter-rouge">vDSP</code> methods in <code class="language-plaintext highlighter-rouge">Accelerate.framework</code> may be much faster). I did my best to use <code class="language-plaintext highlighter-rouge">CVPixelBufferPool</code> allocators where possible and reused the <code class="language-plaintext highlighter-rouge">CIContext</code> for rendering, but perhaps someone with more iOS/visionOS development experience could improve the code.</p> <p>Suffice to say, the <a href="https://github.com/surreality-lab/VisionProDisparityMatching">source code is available on GitHub</a> and I welcome any type of improvement to my code or future innovation. Remember to include your <code class="language-plaintext highlighter-rouge">Enterprise.license</code>, and happy developing!</p>]]></content><author><name></name></author><category term="research"/><category term="vision-pro"/><category term="computer-vision"/><summary type="html"><![CDATA[Implementing stereo matching on AVP with RAFT-Stereo]]></summary></entry><entry><title type="html">My CUTF: Learning Never Ends</title><link href="https://griffinhurt.com/blog/2023/cutf-final/" rel="alternate" type="text/html" title="My CUTF: Learning Never Ends"/><published>2023-12-04T05:00:00+00:00</published><updated>2023-12-04T05:00:00+00:00</updated><id>https://griffinhurt.com/blog/2023/cutf-final</id><content type="html" xml:base="https://griffinhurt.com/blog/2023/cutf-final/"><![CDATA[<p><em>Pssst, I posted this on the <a href="https://pitthonors.blog/2023/12/04/my-cutf-learning-never-ends/">Frederick Honors College Blog</a> initially.</em></p> <p>Today I walked into my Sennott Square classroom for CMPINF 0010: Big Ideas in Computing and Information for the last time this semester. The last class is always somewhat bittersweet, with some students excited that they won’t have to complete weekly skills labs anymore, and others dismayed that they won’t share as many classes with their friends next semester. For me, I try to reflect on the progress the students have made over the semester and cherish the last few final presentations.</p> <p>I certainly learned a lot about teaching, the SCI student experience, and Big Ideas this semester through my CUTF. I mentioned in my previous post that I had noticed a change in the student population this semester: almost my entire class was made up of freshmen instead of upperclassmen like in the spring. Initially, I thought this would mean spending more time with students in office hours fixing small issues, but surprisingly, I only had a few groups come to my office hours over the course of the semester. My hypothesis is that the new students were too busy getting acquainted with Pitt’s campus to visit office hours, but they continually produced code for assignments that exceeded my expectations. Perhaps this group of students came in with more computer science experience or just found the material to be more entertaining.</p> <p>I think the most valuable part of my CUTF experience was the increased responsibility and accountability in teaching throughout the semester. Before the CUTF, I didn’t always have time to inspect the materials for each skills lab as deeply as I would have liked before teaching. I would generally review the lab notebooks the night before my lesson and simply ensure the functionality of the code. However, this semester, I read each one of the lab notebooks the week prior to the lesson and kept a detailed log of the alterations I made to them. Then, I took those changes to our group meetings and discussed them in detail with the rest of the teaching team. By dedicating this time each week to review both the conceptual and technical material, I evaluated my goals both as a student and an educator: what would I want to get out of this course if I were taking it? While I didn’t always have much to add or change, I was always thinking about how the seemingly disconnected topics of the course were truly cohesive, and how to help students build intuition for these relationships.</p> <p>Even though my CUTF has concluded, there’s still plenty of small items in the Big Ideas curriculum I would like to address as a UTA for the class next semester. Each Friday throughout the semester, the teaching staff and UTAs met in a Zoom call to discuss the previous week’s lesson and the current state of the course. At each of those meetings, I took notes on what the other members of the team thought, hoping to consolidate them at the end of the semester so that students in the spring could use improved versions of the labs. Even when I wasn’t actively involved with Big Ideas, the concepts of the course were floating in my mind. During my capstone seminar (CS 1900), I heard several students mention that developing better skills with Git and GitHub would have been beneficial for their internships. This has informed specific changes that I plan to implement in the Big Ideas curriculum covering version control in more detail. On top of changes to the lab content, I hope to finally get the automatic grading software functional for the spring semester. One of the master’s students in the lab I work in is using generative AI to help human graders provide better feedback to students on coding assignments, and I think this technology could be particularly helpful for a course like Big Ideas with many students and short coding assignments.</p> <p>As for my academic plans after this semester, my goal is to graduate at the end of this year and start a Ph.D. either in computer science or intelligent systems. Hopefully these programs will provide me with more opportunities to teach or otherwise mentor students in computing and information sciences. I’m truly grateful for the incredible experience I was afforded through the CUTF. I would encourage any students with a desire to make a positive change in their academic community to design their own project and apply for the fellowship to be the next educational innovator at Pitt.</p>]]></content><author><name></name></author><category term="teaching"/><summary type="html"><![CDATA[A reflection on my Chancellor's Undergraduate Teaching Fellowship.]]></summary></entry><entry><title type="html">The “Big Ideas” of Teaching</title><link href="https://griffinhurt.com/blog/2023/cutf-mid/" rel="alternate" type="text/html" title="The “Big Ideas” of Teaching"/><published>2023-10-25T05:00:00+00:00</published><updated>2023-10-25T05:00:00+00:00</updated><id>https://griffinhurt.com/blog/2023/cutf-mid</id><content type="html" xml:base="https://griffinhurt.com/blog/2023/cutf-mid/"><![CDATA[<p><em>Pssst, I posted this on the <a href="https://pitthonors.blog/2023/10/25/the-big-ideas-of-teaching/">Frederick Honors College Blog</a> initially.</em></p> <p>Teaching CMPINF 0010: Big Ideas in Computing and Information this Fall is both similar and different to last Spring. The largest deviation from last semester is the change in student population: most students taking the course in the Fall are freshmen, while those in the Spring tend to be upperclassmen. Although this has positively affected lab attendance overall, the same topics that caused confusion last semester continue to be pain points. So far, my CUTF project has been moving in the right direction to address these problems. I’ve been able to find at least one correlation between the each of the lab notebooks and the lectures up to this point and made additions to the lesson notebooks accordingly. I was initially concerned that some of the more technical labs would be too far removed from the lecture material, but, fittingly, the concepts in Big Ideas are so ubiquitous across computing that even the most technically scoped lessons are still related to them. While the curriculum restructure has been smooth, I’ve yet to implement an automatic grading solution for the class. JupyterHub is a complicated system under the hood, and even implementing off-the-shelf solutions requires a deep understanding of the software architecture that I haven’t developed yet. I’ve been making incremental progress, though, and hope to have a system working in the next few weeks.</p> <p>Before the end of the semester, to get a better gauge of what aspects of the Big Ideas lab are important to Pitt students, I plan to send a survey to previous students asking for their experience with and opinions on the course. Hopefully, if we garner enough student responses, we can use this information to center our focus on the important details.</p> <p>The work I’ve been performing under the CUTF hasn’t only been related to my project — I have taken on a new role of leadership within the teaching staff. Each week, the instructors for Big Ideas meet to discuss the previous week’s lab and the future of the course. As the undergraduate teaching fellow, if the professors are unable to attend the meeting, I am expected to lead the dialogue, listening to my fellow teaching assistants and taking notes on their thoughts. I am also expected to resolve the issues we discuss: if technical problems arise in a lab notebook, I should make changes to the code. Although these added responsibilities are a deviation from those of a typical undergraduate teaching assistant, I have found that by offering a student’s viewpoint to the curriculum design, I can help ensure the material matches the knowledge level and needs of the student body.</p> <p>Over the course of my time as a teaching assistant, and now as a teaching fellow, several of my peers and students have asked me about the process for getting involved with teaching. Luckily, the School of Computing and Information places a large focus on peer learning, so this process is relatively straightforward. I would recommend any students interested in becoming a teaching assistant in SCI read the guide created by the Pitt Computer Science Club; it covers how to get started and addresses some common problems facing teaching assistants. As part of the process, you’ll have to provide a letter of recommendation from a faculty member indicating your academic ability, complete some training, and schedule your section. If you meet the criteria, you’ll get to lead a lab or recitation section!</p> <p>Although the process of becoming a teaching assistant appears simple, it’s important to establish yourself in the academic community both before and during your time teaching. Coming into college, I knew I wanted to be a professor, so it was important for me to get experience teaching as quickly as I could. When I took Big Ideas with Dr. Lee, I visited his office hours to discuss research opportunities and started attending meetings in his lab outside of class. Additionally, I joined the SCI Academic Council, which he chaired, as the Student Representative. Through this established connection, when it came time for professors to pick teaching assistants for their courses, Dr. Lee selected me for Big Ideas. Even though he didn’t teach the course that semester, my relationship with him through research and Academic Council led to discussions about the course’s future and, eventually, the proposal for my CUTF project.</p> <p>Getting involved in other ways continues to be a driving force in how I receive teaching opportunities. I recently started working on a new project that focuses on teaching students from Pittsburgh Public Schools programming and other technical skills through game design with the Unity engine. The professor in charge of the project, Dr. Dmitriy Babichenko, also teaches CMPINF 1201: Digital Narrative and Interactive Design, centering around using microcontrollers for interactive storytelling. A few weeks ago, he asked me to offer technical support for his class while he was away at a conference. Attending the class not only gave me an opportunity to hone my technical communication skills through teaching, but also get a better understanding of the other interdisciplinary programs offered through SCI. So, above all else, getting involved as much as you possibly can is the best advice I could give to students who want to start teaching. Even if it takes time to find the right teaching opportunity for you, getting involved will open new doors that you didn’t even know existed.</p>]]></content><author><name></name></author><category term="teaching"/><summary type="html"><![CDATA[The midpoint of my Chancellor's Undergraduate Teaching Fellowship.]]></summary></entry><entry><title type="html">My CUTF Introduction</title><link href="https://griffinhurt.com/blog/2023/cutf-intro/" rel="alternate" type="text/html" title="My CUTF Introduction"/><published>2023-09-25T05:04:36+00:00</published><updated>2023-09-25T05:04:36+00:00</updated><id>https://griffinhurt.com/blog/2023/cutf-intro</id><content type="html" xml:base="https://griffinhurt.com/blog/2023/cutf-intro/"><![CDATA[<p><em>Pssst, I posted this on the <a href="https://pitthonors.blog/2023/09/25/cutf-introduction-griffin-hurt/">Frederick Honors College Blog</a> initially.</em></p> <p>Last fall, I started my education at the University of Pittsburgh pursuing a degree in computer science, and one of the first courses I took was CMPINF 0010: Big Ideas in Computing and Information. The course is a general education requirement in the School of Computing and Information and centers around some of the overarching themes in computer and information science, including computational thinking, communication, and design and affordances. Big Ideas is a 4-credit class, with 3 credits allocated to a lecture component and a 1-credit weekly skills lab.</p> <p>When I took the course, I truly enjoyed attending the lectures. My professor, Dr. Adam Lee, was an incredible orator and always maintained my interest in the subject matter, even though I already had 10 years of coding experience by the time I entered college. Whenever we discussed material that seemed abstract, he would provide real-world examples as motivation for how we could apply the concepts to our own work. Sometimes, we would have a guest lecture from another important figure in computer/information science, which provided us with more insight into how the ideas were being used to solve real-world problems.</p> <p>The lab component started out strong as well. We were working in a new programming environment that I didn’t have much experience in, and my undergraduate teaching assistant for the class was engaging. However, as the weeks went on, students began to realize that the concepts from the lecture and the lab lessons were not related, and they engaged less with the material. Halfway through the semester, lab attendance had noticeably dropped.</p> <p>During my second semester at Pitt, I signed up to be an undergraduate teaching assistant for the course because I had found the concepts so interesting. This meant answering emails with questions about the course, holding office hours, and, most enthralling to me, teaching one of the lab sections. After a few weeks of teaching, I realized that, like when I took the course, attendance for the skills labs had decreased. After discussing attendance with a few students and friends who had taken the course, I realized that the lack of a connection between the lecture concepts and the lab assignments played a large part in why students were losing interest.</p> <p>That brings me to my project for the Chancellor’s Undergraduate Teaching Fellowship. My name is Griffin Hurt, and I am studying computer science with a secondary focus in mathematics. With Dr. Adam Lee as my faculty mentor, I plan to update the lab lessons for Big Ideas to include material from the lectures, hopefully bridging the gap between the two parts of the course. Originally, the lab was designed to provide students with a working knowledge of an array of technical skills that will serve them as they advance through any computationally oriented degree program, as opposed to specifically reinforcing lecture. By connecting the two, we hope that students will learn to apply the themes covered in lecture, while still gaining the required technical skills. Lab lessons are presented as Jupyter notebooks, which are collections of combined code and text, so my updates will generally involve adding additional text elements and code examples referencing the previous week’s big ideas.</p> <p>In addition, I plan to implement an automatic grader for the lab assignments as part of my fellowship. When students turn in labs, they are not offered any immediate feedback and must wait for teaching assistants to grade the assignments. Given that most students in the course are working with these technologies for the first time, I believe that providing students with a formative assessment of their code as they work can help improve their learning.</p> <p>I am grateful that the Frederick Honors College has provided me with this incredible opportunity and look forward to seeing the results of my project. After I finish my undergraduate degree, I hope to attend graduate school and become a professor someday. I believe the Chancellor’s Undergraduate Teaching Fellowship will provide me with important skills related to teaching, including curriculum design and understanding students’ mindsets. By enhancing the Big Ideas course and igniting a passion for learning in new students, I hope to contribute to a more enriching experience for those entering the School of Computing and Information, shaping the future of computer and information science education.</p>]]></content><author><name></name></author><category term="teaching"/><summary type="html"><![CDATA[An introduction to my Chancellor's Undergraduate Teaching Fellowship project.]]></summary></entry><entry><title type="html">What’s with the blog’s name?</title><link href="https://griffinhurt.com/blog/2023/blog-title/" rel="alternate" type="text/html" title="What’s with the blog’s name?"/><published>2023-01-12T05:00:00+00:00</published><updated>2023-01-12T05:00:00+00:00</updated><id>https://griffinhurt.com/blog/2023/blog-title</id><content type="html" xml:base="https://griffinhurt.com/blog/2023/blog-title/"><![CDATA[<p>Ah, the Pythagorean theorem, one of the most ubiquitous and useful formulas in all of math. If you have a right triangle with side lengths \(a\), \(b\), and \(c\), they are related by the following formula:</p> \[a^2 + b^2 = c^2\] <p>If \(a\), \(b\), and \(c\) are all integers, this is known as a “Pythagorean triple”. Two examples are the 3-4-5 and 5-12-13 triangles. It’s relatively simple to prove that there are an infinite number of these Pythagorean triples, and there are <a href="https://math.stackexchange.com/questions/1386029/are-there-infinitely-many-pythagorean-triples">formulas to produce all of them from the set of positive integers</a>. But what if I change the formula to instead be:</p> \[a^n + b^n = c^n\] \[n \geq 3\] <p>Are there any integer solutions to this equation?</p> <p>Enter Pierre de Fermat, a 17th century mathematician specializing in number theory and infintesimal calculus. While reading a copy of <em>Arithmetica</em> by Diophantus, he came across problem II.8, which considers solving the Pythagorean theorem for a known \(c\). Around 1637, he wrote the following statement in Latin next to the problem:</p> <blockquote> <p>Cubum autem in duos cubos, aut quadratoquadratum in duos quadratoquadratos &amp; generaliter nullam in infinitum ultra quadratum potestatem in duos eiusdem nominis fas est dividere cuius rei demonstrationem mirabilem sane detexi. <strong>Hanc marginis exiguitas non caperet.</strong></p> </blockquote> <p>or in English:</p> <blockquote> <p>It is impossible to separate a cube into two cubes, or a fourth power into two fourth powers, or in general, any power higher than the second, into two like powers. I have discovered a truly marvelous proof of this, which <strong>this margin is too narrow to contain.</strong></p> </blockquote> <p>Fermat died in 1665 without ever publishing a proof of the statement (although he did send the problem to his friends as a challenge). After his death, his son published a new version of <em>Arithmetica</em> with Fermat’s comments, as well as his proof of the \(a^4 + b^4 = c^4\) case. However, the cubic version consistently perplexed mathematicians for the next couple hundred years, so much so that the Guiness Book of World Records labeled it the “most difficult mathematical problem”… until the 1980s came around.</p> <p>In 1986, mathematician Gerhard Frey suggested that proving the modularity theorem (then known as the Taniyama–Shimura-Weil conjecture) would imply Fermat’s Last Theorem, and by 1990, Jean-Pierre Serre and Ken Ribet assisted in proving this notion. So then it’s simple, right? Just prove the modularity theorem and you have the solution to a 300 year old unsolved problem! The issue is that most mathematicians at the time thought the conjecture would be extremely difficult, if not impossible to prove. One of them was even Ken Ribet.</p> <p>After learning about the advancements made in Fermat’s Last Theorem, Cambridge professor Andrew Wiles began working on a proof of the modularity theorem for semistable elliptic curves, and in turn, Fermat’s Last Theorem. After years of hard work, on June 23rd, 1993 Wiles presented his findings in three lectures at the Isaac Newton Institute for Mathematical Sciences in Cambridge. However, there was a problem. During review, referees raised some questions to Wiles that made him realize his proof was actually incomplete. Rumors began to spread about the proof, and there was mounting pressure in the mathematical community for him to release his current work, as it was still useful without proving Fermat’s Last Theorem. Wiles spent the next year attempting to fix his proof with one of his former students to no avail.</p> <p>September 19, 1994 was a Monday morning. Wiles was on the edge of giving up and publishing his current work. Suddenly, he came to a realization, which is best defined in his own words:</p> <blockquote> <p>I was sitting at my desk examining the Kolyvagin–Flach method. It wasn’t that I believed I could make it work, but I thought that at least I could explain why it didn’t work. Suddenly I had this incredible revelation. I realised that, the Kolyvagin–Flach method wasn’t working, but it was all I needed to make my original Iwasawa theory work from three years earlier. So out of the ashes of Kolyvagin–Flach seemed to rise the true answer to the problem. It was so indescribably beautiful; it was so simple and so elegant. I couldn’t understand how I’d missed it and I just stared at it in disbelief for twenty minutes. Then during the day I walked around the department, and I’d keep coming back to my desk looking to see if it was still there. It was still there. I couldn’t contain myself, I was so excited. It was the most important moment of my working life. Nothing I ever do again will mean as much.</p> </blockquote> <p>The final result was over one hundred pages and almost incomprehensible, except to the highest level mathematicians. The Wikipedia page that has a summary of the proof says “This section needs attention from an expert in mathematics,” which is a bit of an understatement. Ribet later stated that he believed Andrew Wiles was one of the only people on Earth that could have created the proof. Although he was too old to win a Fields Medal (the equivalent to a Nobel Prize in Mathematics) for his work, he was knighted, fittingly won the Fermat Prize for the year, and a received a variety of other awards.</p> <p>The question that mathematicians are still wondering about now is whether Fermat ever actually had a proof for the cubic case. He probably didn’t have working knowledge of the modularity of semistable elliptic curves, as they hadn’t really been discovered yet. Perhaps Fermat had created an incorrect demonstration for the \(n = 3\) case that he was convinced was right, similar to Wiles’s original 1993 proof. We’ll probably never know what actually happened, but it’s certainly fun to think about.</p> <p>Surprisingly, this isn’t the only 300 year old problem solved at the turn of the millenium. University of Pittsburgh’s own Thomas Hales announced a proof of the Kepler conjecture, first proposed in 1611, in 1998. However, he used a computer-assisted proof, so it took until 2017 to be formalized and accepted into a journal. If you’re one of my students in Big Ideas (CMPINF 0010) this semester, you might even be lucky enough to get a speech from him about computer-assisted proofs and the future of computers in solving difficult mathematical problems.</p> <p>Now, if you’re a budding mathematician yourself and now concerned that all the good problems have been solved already, fear not! The Millenium Problems are a set of seven unsolved mathematical questions with a one-million dollar reward to anyone who can find answers. Only one has been solved so far: the Poincaré conjecture covering the characterization of the 3-sphere (think sphere in 4 dimensions) was proven by Grigori Perelman in 2002. The story of Perelman’s proof of the Poincaré conjecture is worth a whole blog post in itself, so I’ll just file that away for another time. Until then, keep working hard.</p> <p>- Griffin</p> <p>Sources:</p> <ul> <li><a href="https://en.wikipedia.org/wiki/Modularity_theorem">https://en.wikipedia.org/wiki/Modularity_theorem</a></li> <li><a href="https://en.wikipedia.org/wiki/Wiles%27s_proof_of_Fermat%27s_Last_Theorem">https://en.wikipedia.org/wiki/Wiles%27s_proof_of_Fermat%27s_Last_Theorem</a></li> <li><a href="https://en.wikipedia.org/wiki/Fermat_Prize">https://en.wikipedia.org/wiki/Fermat_Prize</a></li> <li><a href="https://en.wikipedia.org/wiki/Andrew_Wiles">https://en.wikipedia.org/wiki/Andrew_Wiles</a></li> <li><a href="https://en.wikipedia.org/wiki/Kepler_conjecture">https://en.wikipedia.org/wiki/Kepler_conjecture</a></li> <li><a href="https://en.wikipedia.org/wiki/Millennium_Prize_Problems">https://en.wikipedia.org/wiki/Millennium_Prize_Problems</a></li> </ul> <p>(Yes, I know Wikipedia is not a scholarly source, but this is just meant to be a fun blog post. Take it with a grain of salt.)</p>]]></content><author><name></name></author><category term="meta"/><category term="math"/><summary type="html"><![CDATA[An explanation of the strange title of this blog]]></summary></entry></feed>