使用Genie可视化线性算子的动作
本文致力于应用GenieFramework开发一个交互式web应用程序,演示线性算子的动作。 作为一个例子,我们考虑使用2x2矩阵表示圆的一组点的变换。 Stipple和PlotlyBase包用于实现。 文本详细描述了代码的关键元素,并在相关片段之后进行了解释。 特别注意使用响应式宏的理由 @in 和 @out 控制矩阵的元素(m11, m12, m21, m22),以及使用自定义类型的可能性,例如 mutable struct,基于点画文档。
应用概念
附录说明了2x2矩阵作为线性算子对二维点集的影响。 最初,这些点形成半径为1的圆,用户可以使用滑块更改矩阵的元素,观察拉伸,压缩或旋转等变换的影响。 这种方法通过提供学习线性代数的交互式工具具有教育潜力。
从一组点创建一个圆
using GenieFramework, Stipple, Stipple.ReactiveTools, StippleUI, PlotlyBase
const circ_range = -1:0.05:1
const circle = [[i, j] for i in circ_range for j in circ_range if i^2 + j^2 <= 1]
const x_axis_points = findall(x -> x[1] == 0 && x[2] >= 0, circle)
const y_axis_points = findall(x -> x[2] == 0 && x[1] >= 0, circle)
const circle_matrix = Base.stack(circle)
该片段形成可视化的初始数据。 范围被定义 circ_range -1到1,x和y坐标以0.05为增量。 使用列表包含生成坐标对。 [i, j] 由圆方程过滤 i^2 + j^2 <= 1,这给出了一组近似半径为1的圆的点。 变量 x_axis_points 和 y_axis_points 它们分别包含位于Y轴和X轴正部分上的点的索引,以突出显示基向量。 功能 Base.stack 将坐标列表转换为矩阵,其中第一行是x坐标,第二行是y坐标。 常量(const)用于不可变的数据。 离散步骤导致圆的一些逐步轮廓,但该方法实现简单。
开发图形转换函数
function create_plot_data(m11::Float64, m12::Float64, m21::Float64, m22::Float64)
transformed = [m11 m12; m21 m22] * circle_matrix
[
scatter(x=transformed[1, :], y=transformed[2, :], mode="markers", name="Точки круга"),
scatter(x=transformed[1, x_axis_points], y=transformed[2, x_axis_points], name="Ось Y"),
scatter(x=transformed[1, y_axis_points], y=transformed[2, y_axis_points], name="Ось X", aspect_ratio=:equal)
]
end
const initial_plot_data = create_plot_data(1.0, 0.0, 0.0, 1.0)
功能 create_plot_data 负责转换点并为图形准备数据。 接受四个参数—2x2矩阵的元素(m11, m12, m21, m22). 执行矩阵乘法 circle_matrix,获取点的新坐标 transformed. 返回三个对象的数组 scatter:圆的所有点,Y轴上的点和X轴上的点。 参数 aspect_ratio=:equal 提供轴的均匀比例。 常数 initial_plot_data 用不改变圆的单位矩阵设置图形的初始状态。
配置图形布局
const plot_layout = PlotlyBase.Layout(
title="Линейное преобразование круга",
xaxis=attr(title="Ось X", showgrid=true, range=[-2, 2]),
yaxis=attr(title="Ось Y", showgrid=true, range=[-2, 2]),
width=600, height=550
)
该片段使用以下方法定义图形布局 PlotlyBase.Layout. 设置了标题、轴标签、网格和值范围从-2到2。 图形尺寸是固定的:宽600像素,高550像素。 布局声明为常量,因为它在应用程序运行期间不会更改。
确保反应性
@app begin
@in m11 = 1.0
@in m12 = 0.0
@in m21 = 0.0
@in m22 = 1.0
@out plot_data = initial_plot_data
@out plot_layout = plot_layout
@onchange m11, m12, m21, m22 begin
plot_data = create_plot_data(m11, m12, m21, m22)
end
end
座 @app 定义响应式应用程序模型。 宏 @in 将矩阵元素声明为具有对应于单位矩阵的初始值的输入变量。 宏 @out 设置输出数据: plot_data 对于时间表和 plot_layout 为布局。 宏 @onchange 跟踪值的变化 m11, m12, m21, m22 和原因 create_plot_data 要更新 plot_data.
自定义用户界面
function ui()
sliders = [row([column([h6("m$(i)$(j)={{m$(i)$(j)}}"), slider(-2:0.1:2, Symbol("m$(i)$(j)"), color="purple")], size=3) for j in 1:2]) for i in 1:2]
[
row([
column(sliders, size=4),
column(plot(:plot_data, layout=:plot_layout))
], size=3)
]
end
@page("/", ui)
功能 ui 形成接口。 变量 sliders 创建一个由两行组成的数组,每行包含两个带有标题的滑块(m11, m12, m21, m22). 滑块的范围从-2到2,增量为0.1。 接口由行(row)有两列:左边的滑块,右边的图形,通过 plot. 宏 @page 将接口绑定到根路由"/"。
申请的需要 @in 和 @out
点画中的反应性
Stipple实现了响应式模型,确保数据和接口的同步。 宏 @in 和 @out 将元素集成到此模型中。 @in 将数据绑定到界面元素(滑块),允许用户更改它们。 @out 状态改变时更新输出数据(图形)。 使用标准广告时,例如 m11 = 1.0 接口元素失去与值的连接,不包括它们的修改; @onchange 它没有响应,因为点画不跟踪这些数据;交互性被破坏,因为值没有传递给JavaScript。
自定义类型的替代方案
根据Stipple文档(Types of variables in Stipple),有可能使用 mutable struct 作为反应变量:
mutable struct MatrixState
m11::Float64
m12::Float64
m21::Float64
m22::Float64
end
@app begin
@in state = MatrixState(1.0, 0.0, 0.0, 1.0)
@out plot_data = initial_plot_data
@out plot_layout = plot_layout
@onchange state begin
plot_data = create_plot_data(state.m11, state.m12, state.m21, state.m22)
end
end
结构 MatrixState 通过 @in,这允许Stipple跟踪其字段的变化。 但是,在此应用中,优先考虑单个变量(@in m11 等。),因为这通过单独的滑块简化了矩阵元素的管理。
没有 @in 和 @out 矩阵元素在Julia中保持隔离,而不与界面交互。 响应式宏或 mutable struct 与 @in/@out 它们提供必要的通信,方法的选择取决于数据结构和接口要求。
要启动应用程序,我们将使用[以前的статьям]中已经熟悉的应用程序(https://engee.com/community/ru/catalogs/projects/tablo-aeroporta-s-dinamicheskoi-tablitsei-v-genieframework )由建筑:
using Markdown
cd(@__DIR__)
app_url = string(engee.genie.start(string(@__DIR__,"/app.jl")))
Markdown.parse(match(r"'(https?://[^']+)'",app_url)[1])
结论
本文演示了如何使用GenieFramework创建一个可视化线性算子动作的交互式应用程序。 响应式宏 @in 和 @out 我们提供了接口和逻辑之间的链接,以及使用的可能性 mutable struct 为复杂场景提供灵活性。 该应用程序突出了Genie开发教育工具的能力。---