Index 扉へ 首頁
人類の品種・宇宙人・系外銀河など
Pure functional programming via simulation library (simulationライブラリで純粋な関数型プログラミング)
0   商湯      2025年1月23日 木 15:18
Download source files:
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>();
}
この記事は 2026年2月4日 水 11:12 に作者によって編集されました
1   商湯      2025年1月23日 木 15:22
サンプルです

(太陽と地球の万有引力のシミュレーションです
ボタン二つで太陽と地球を表示しています)

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();
           }
       }
   }
}
2   商湯      2026年2月4日 水 10:52
「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;
       }
   }
}
名前      編集用パスワード(省略可)    パスワードの記憶
数式 αβγ IPA http:// 画像 B I U 上 下
(添付ファイルは http://www.jkofsp.net/up/ にアップロードしてください)