| Pure functional programming via simulation library (simulationライブラリで純粋な関数型プログラミング) |
|---|
|
Download source files:
この記事は 2026年2月4日 水 11:12 に作者によって編集されましたhttp://www.jkofsp.net/files/ Pure functional programming via simulation library (simulationライブラリで純粋な関数型プログラミングをします) (ライブラリの他にサンプルも付いています) (C++) http://www.jkofsp.net/bbs/topic.aspx?id=117-0 (F#) http://www.jkofsp.net/bbs/topic.aspx?id=204-0 multi manager version: (multi managerでは複数のサブシステムを切り替えられます) (C#) http://www.jkofsp.net/bbs/topic.aspx?id=335-0 (C++) http://www.jkofsp.net/bbs/topic.aspx?id=336-0 Equation(方程式) C#&F#: http://www.jkofsp.net/bbs/topic.aspx?id=337-0 StateX (C#&F#) http://www.jkofsp.net/bbs/topic.aspx?id=338-0 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Takaku.Simulation { public interface ICached { void Flush(); } public class ManagerCached { public static ManagerCached TheManagerCached = new ManagerCached(); private LinkedList<ICached> Cacheds = new LinkedList<ICached>(); public void Add(ICached cached) { Cacheds.AddLast(cached); } public void Remove(ICached cached) { Cacheds.Remove(cached); } public void Flush() { foreach(ICached i in Cacheds) i.Flush(); } } public class Cached<T> : ICached { private Func<T> FuncValue; private T Value; private bool Calculated; public Cached(Func<T> funcValue) { FuncValue = funcValue; Calculated = false; ManagerCached.TheManagerCached.Add(this); } public void Remove() { ManagerCached.TheManagerCached.Remove(this); } public T v() { if (Calculated) return Value; else { Calculated = true; return Value = FuncValue(); } } public static implicit operator T(Cached<T> x){ return x.v(); } public void Flush() { Calculated = false; } } public interface IState { void Update(); void Flush(); } public class ManagerState { public static ManagerState TheManagerState = new ManagerState(); private LinkedList<IState> States = new LinkedList<IState>(); public void Add(IState state) { States.AddLast(state); } public void Remove(IState state) { States.Remove(state); } public void Update() { foreach(IState i in States) i.Update(); } public void Flush() { foreach(IState i in States) i.Flush(); } } public class State<T> : IState { private Func<T,T> FuncState; private T Current, Next; public State(T defaultValue, Func<T,T> funcState) { Current = defaultValue; FuncState = funcState; ManagerState.TheManagerState.Add(this); } public void Remove() { ManagerState.TheManagerState.Remove(this); } public T v() { return Current; } public static implicit operator T(State<T> x){ return x.v(); } public void Update() { Next = FuncState(Current); } public void Flush() { Current = Next; } } public interface IDiff { void Update(); } public class ManagerDiff { public static ManagerDiff TheManagerDiff = new ManagerDiff(); private LinkedList<IDiff> Diffs = new LinkedList<IDiff>(); public void Add(IDiff diff) { Diffs.AddLast(diff); } public void Remove(IDiff diff) { Diffs.Remove(diff); } public void Update() { foreach (IDiff i in Diffs) i.Update(); } } public class Diff<T> : IDiff { public static Func<T, T, T> FuncSub; private Func<T> FuncValue; private T Old, _d; public Diff(T defaultValue, Func<T> funcValue) { Old = defaultValue; FuncValue = funcValue; ManagerDiff.TheManagerDiff.Add(this); } public void Remove() { ManagerDiff.TheManagerDiff.Remove(this); } public T d() { return _d; } public static implicit operator T(Diff<T> x){ return x.d(); } public void Update() { T _new = FuncValue(); _d = FuncSub(_new, Old); Old = _new; } } public interface ISimulationRemovable { void RemoveSimulation(); } public delegate T Bind<T>(); } |
|
サンプルです
(太陽と地球の万有引力のシミュレーションです ボタン二つで太陽と地球を表示しています) namespace SimulationCSharp { partial class Form1 { /// <summary> /// 必要なデザイナー変数です。 /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 使用中のリソースをすべてクリーンアップします。 /// </summary> /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows フォーム デザイナーで生成されたコード /// <summary> /// デザイナー サポートに必要なメソッドです。このメソッドの内容を /// コード エディターで変更しないでください。 /// </summary> private void InitializeComponent() { this.btnSun = new System.Windows.Forms.Button(); this.btnEarth = new System.Windows.Forms.Button(); this.SuspendLayout(); // // btnSun // this.btnSun.Location = new System.Drawing.Point(115, 108); this.btnSun.Name = "btnSun"; this.btnSun.Size = new System.Drawing.Size(41, 39); this.btnSun.TabIndex = 0; this.btnSun.Text = "Sun"; this.btnSun.UseVisualStyleBackColor = true; // // btnEarth // this.btnEarth.Location = new System.Drawing.Point(204, 108); this.btnEarth.Name = "btnEarth"; this.btnEarth.Size = new System.Drawing.Size(41, 39); this.btnEarth.TabIndex = 1; this.btnEarth.Text = "Earth"; this.btnEarth.UseVisualStyleBackColor = true; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(284, 262); this.Controls.Add(this.btnEarth); this.Controls.Add(this.btnSun); this.Name = "Form1"; this.Text = "Form1"; this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.Form1_FormClosed); this.Load += new System.EventHandler(this.Form1_Load); this.Shown += new System.EventHandler(this.Form1_Shown); this.ResumeLayout(false); } #endregion private System.Windows.Forms.Button btnSun; private System.Windows.Forms.Button btnEarth; } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Takaku.Simulation; namespace SimulationCSharp { public partial class Form1 : Form { bool Exit = false; struct Vec { public double X, Y; public Vec(double x, double y) { X = x; Y = y; } public double Norm() { return Math.Sqrt(X * X + Y * Y); } public static Vec operator +(Vec v1, Vec v2) { return new Vec(v1.X + v2.X, v1.Y + v2.Y); } public static Vec operator -(Vec v1, Vec v2) { return new Vec(v1.X - v2.X, v1.Y - v2.Y); } public static Vec operator *(double k, Vec v) { return new Vec(k * v.X, k * v.Y); } public static Vec operator *(Vec v, double k) { return new Vec(v.X * k, v.Y * k); } public static Vec operator /(Vec v, double k) { return new Vec(v.X / k, v.Y / k); } } public Form1() { InitializeComponent(); } private double AU = 149597870691; // m private double Year = 3600 * 24 * 365.256363004; private double G = 6.67300e-11; // m3*kg-1*s-2 private double M = 1.98892e30; // kg 太阳 private double m = 5.9742e24; // kg 地球 private Vec vm0 = new Vec(30287, 0); // m/s 在近日点的速度 double TScale = 3600 * 24 * 7; double dt; long t1 = DateTime.Now.Ticks / 1000000; State<Vec> sM; State<Vec> sm; State<Vec> vM; State<Vec> vm; Cached<Vec> r_mM; Cached<Vec> r_Mm; Cached<Vec> gm; Cached<Vec> gM; private void Form1_Load(object sender, EventArgs e) { r_mM = new Cached<Vec>(() => sM.v() - sm.v()); r_Mm = new Cached<Vec>(() => sm.v() - sM.v()); gm = new Cached<Vec>(() => G * M * r_mM.v() / Math.Pow(r_mM.v().Norm(), 3)); gM = new Cached<Vec>(() => G * m * r_Mm.v() / Math.Pow(r_Mm.v().Norm(), 3)); sM = new State<Vec>(new Vec(0.0, 0.0), (x) => x + vM.v() * dt); sm = new State<Vec>(new Vec(0.0, 0.9832898912 * AU), (x) => x + vm.v() * dt); // 近日点 vM = new State<Vec>(new Vec(0.0, 0.0), (x) => x + gM.v() * dt); vm = new State<Vec>(vm0, (x) => x + gm.v() * dt); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { Exit = true; } private void Form1_Shown(object sender, EventArgs e) { while (Exit == false) { long t2 = DateTime.Now.Ticks / 1000000; dt = TScale * Math.Min(t2 - t1, 0.05); t1 = t2; ManagerState.TheManagerState.Update(); btnSun.Left = this.Width / 2 + (int)(100.0 * sM.v().X / AU); btnSun.Top = this.Height / 2 - (int)(100.0 * sM.v().Y / AU); btnEarth.Left = this.Width / 2 + (int)(100.0 * sm.v().X / AU); btnEarth.Top = this.Height / 2 - (int)(100.0 * sm.v().Y / AU); ManagerCached.TheManagerCached.Flush(); ManagerState.TheManagerState.Flush(); Application.DoEvents(); } } } } |
|
「Dual<T>」の実装です
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Takaku.Simulation { public interface IDual { void Flush(); } public class ManagerDual { public static ManagerDual TheManagerDual = new ManagerDual(); private LinkedList<IDual> Duals = new LinkedList<IDual>(); public void Add(IDual dual) { Duals.AddLast(dual); } public void Remove(IDual dual) { Duals.Remove(dual); } public void Flush() { foreach (IDual i in Duals) i.Flush(); } } public class Dual<T> : IDual { private T _Current, _Next; public Dual(T defaultValue) { _Current = defaultValue; ManagerDual.TheManagerDual.Add(this); } public void Remove() { ManagerDual.TheManagerDual.Remove(this); } public T Current { get { return _Current; } } public T Next { set { _Next = value; } } public void Flush() { _Current = _Next; } } } |