ラズパイのネットワークI/Fを、GUIで変更した時の写真のメモ
User Mobile Agent と Mobility Agentは どちらが正しいですか
「Mobile Agent」と「Mobility Agent」は異なる概念を指しますが、どちらも「正しい」といえます。これらは用途や文脈に応じて使われます。
- Mobile Agent:
- 一般的に、ネットワーク上で自律的に移動し、タスクを実行するソフトウェアのことを指します。
- この用語は、特に分散コンピューティングや情報処理の分野で使用されます。
- Mobility Agent:
- この用語は、モビリティや交通の文脈で使用されることが多く、移動や交通に関するシステムやサービスを指す場合があります。
- 例えば、交通管理システムやスマートシティのプロジェクトにおける移動の管理や分析を行うエージェントを指すことがあります。
どちらの用語も、その分野や文脈に応じて適切に使用されます。
なるほど
『つまりMobile Agent:は、コンピュータで使われるソフトウェアであって、マルチエージェントシミュレーションのエージェントのことではない。マルチエージェントシミュレーション上で、移動するエージェントのことをMobility Agent:という』
と解釈した(江端)。
Mobile Agent:の例としては、ネットワーク管理エージェント、データマイニングエージェント、Eコマース取引エージェント、負荷分散エージェントのようなもので、マルチエージェントシミュレーション上で移動させるエージェントとは全く違う概念
以上
SELECT * FROM records WHERE start_at = '2023-03-20 05:03:00'; を"2023-03-20"が含まれているものだけを条件にするには、どのようなSQL文になりますか
SELECT * FROM records WHERE start_at = '2023-03-20 05:03:00'; を"2023-03-20"が含まれているものだけを条件にするには、どのようなSQL文になりますか
SELECT * FROM records WHERE start_at::date = '2023-03-20';
プログラムはこちら
// f:\しゅらばしゅう\有吉先生データ\Moove\2023-07/test5.go
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
type Location struct {
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
}
type Record struct {
ID int `json:"id"`
UserID int `json:"user_id"`
Distance float64 `json:"distance"`
Place []Location `json:"place"`
Speed []float64 `json:"speed"`
Prediction int `json:"prediction_type"`
StartAt string `json:"start_at"`
EndAt string `json:"end_at"`
}
func main() {
// PostgreSQL データベースへの接続情報
const (
host = "192.168.0.23"
port = 15432
user = "postgres"
password = "password"
dbname = "moove"
)
// PostgreSQL データベースへの接続
dbinfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
db, err := sql.Open("postgres", dbinfo)
if err != nil {
panic(err)
}
defer db.Close()
fmt.Println("Successfully connected!")
// 検索したい日付
var targetDate string = "2023-03-03"
// 特定の日付を含むレコードを取得するクエリ
query := fmt.Sprintf("SELECT id, user_id FROM records WHERE start_at::date = '%s'", targetDate)
fmt.Println("pass1")
rows, err := db.Query(query)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
fmt.Println("pass2")
// 各行を繰り返し処理
for rows.Next() {
// ここには、取得したいカラムに応じた変数を定義します
var column1, column2 int // これは、idとuser_idのことです
// 必要に応じて他のカラムも追加
err := rows.Scan(&column1,&column2)
if err != nil {
log.Fatal(err)
}
fmt.Println(column1, column2) // 取得したデータを出力
// 他のカラムも出力する場合は、ここに追加
}
// 繰り返し処理後のエラーをチェック
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}
NAT購入したのですが、設置場所のセグメントが、メインのセグメントと違ったので、ポートフォワードで対応しました
先日、1年分の研究成果がぎっしり詰ったPCが、立ち上がらなくなるというシャレにならない状況に直面し、昨日、2TBのNASを購入しました(以下の話と関係があります)。
NASは、できるだけ風通しのよい温度の低い環境の設置が望ましいので、液晶テレビの外付けHDDが置いている場所に併設しようと思いましたが、テレビ用のネットワークを別セグメントにしていたため、NASのIPが届かないことが判明しました。
ルータをブリッジモードにすれば良いのですが、そうすると既存の設定にも影響が出てきそうなの(というか、間違いなく問題が発生するだろう)で、できるだけルータの構成をかえずに対応したいと思いました。
で、ChatGPTに、以下の質問して、回答を貰いました。
私は、SMBだけ通れば良いので、ルータに以下の設定(ポート転送)をしました。
(めずらしく)さくっと、NASが通りました。
これで、研究成果が吹き飛ぶという恐怖が、幾分軽減しました。
PythonのGAで色々なんとかする
Pythonを使った因子分析のコード を そのまま使わせて頂いています。
【Pythonで行う】因子分析
# ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ python3 main3.py
# ライブラリのインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
from factor_analyzer import FactorAnalyzer
# データの読み込み
df_workers = pd.read_csv("sample_factor.csv")
print(df_workers)
# 変数の標準化
df_workers_std = df_workers.apply(lambda x: (x-x.mean())/x.std(), axis=0)
# 固有値を求める
ei = np.linalg.eigvals(df_workers.corr())
print("固有値", ei)
# 因子分析の実行
fa = FactorAnalyzer(n_factors=2, rotation="promax")
fa.fit(df_workers_std)
# 因子負荷量,共通性
loadings_df = pd.DataFrame(fa.loadings_, columns=["第1因子", "第2因子"])
loadings_df.index = df_workers.columns
loadings_df["共通性"] = fa.get_communalities()
print(loadings_df)
# 因子負荷量の二乗和,寄与率,累積寄与率
var = fa.get_factor_variance()
df_var = pd.DataFrame(list(zip(var[0], var[1], var[2])),
index=["第1因子", "第2因子"],
columns=["因子負荷量の二乗和", "寄与率", "累積寄与率"])
print(df_var.T)
# バイプロットの作図
score = fa.transform(df_workers_std)
coeff = fa.loadings_.T
fa1 = 0
fa2 = 1
labels = df_workers.columns
annotations = df_workers.index
xs = score[:, fa1]
ys = score[:, fa2]
n = score.shape[1]
scalex = 1.0 / (xs.max() - xs.min())
scaley = 1.0 / (ys.max() - ys.min())
X = xs * scalex
Y = ys * scaley
for i, label in enumerate(annotations):
plt.annotate(label, (X[i], Y[i]))
for j in range(coeff.shape[1]):
plt.arrow(0, 0, coeff[fa1, j], coeff[fa2, j], color='r', alpha=0.5,
head_width=0.03, head_length=0.015)
plt.text(coeff[fa1, j] * 1.15, coeff[fa2, j] * 1.15, labels[j], color='r',
ha='center', va='center')
plt.xlim(-1, 1)
plt.ylim(-1, 1)
plt.xlabel("第1因子")
plt.ylabel("第2因子")
plt.grid()
plt.show()
Pythonを使ったGAのコード を そのまま使わせて頂いています。
【python】遺伝的アルゴリズム(Genetic Algorithm)を実装してみる
遺伝配列を0/1を、便宜的に0~4にして動くよう、一部改造させて頂いております。
# ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ python3 ga.py
import numpy as np
import matplotlib.pyplot as plt
class Individual:
'''各個体のクラス
args: 個体の持つ遺伝子情報(np.array)'''
def __init__(self, genom):
self.genom = genom
self.fitness = 0 # 個体の適応度(set_fitness関数で設定)
self.set_fitness()
def set_fitness(self):
'''個体に対する目的関数(OneMax)の値をself.fitnessに代入'''
self.fitness = self.genom.sum()
def get_fitness(self):
'''self.fitnessを出力'''
return self.fitness
def mutate(self):
'''遺伝子の突然変異'''
tmp = self.genom.copy()
i = np.random.randint(0, len(self.genom) - 1)
# tmp[i] = float(not self.genom[i])
tmp[i] = np.random.randint(0, 5) # 江端修正
self.genom = tmp
self.set_fitness()
def select_roulette(generation):
'''選択の関数(ルーレット方式)'''
selected = []
weights = [ind.get_fitness() for ind in generation]
norm_weights = [ind.get_fitness() / sum(weights) for ind in generation]
selected = np.random.choice(generation, size=len(generation), p=norm_weights)
return selected
def select_tournament(generation):
'''選択の関数(トーナメント方式)'''
selected = []
for i in range(len(generation)):
tournament = np.random.choice(generation, 3, replace=False)
max_genom = max(tournament, key=Individual.get_fitness).genom.copy()
selected.append(Individual(max_genom))
return selected
def crossover(selected):
'''交叉の関数'''
children = []
if POPURATIONS % 2:
selected.append(selected[0])
for child1, child2 in zip(selected[::2], selected[1::2]):
if np.random.rand() < CROSSOVER_PB:
child1, child2 = cross_two_point_copy(child1, child2)
children.append(child1)
children.append(child2)
children = children[:POPURATIONS]
return children
def cross_two_point_copy(child1, child2):
'''二点交叉'''
size = len(child1.genom)
tmp1 = child1.genom.copy()
tmp2 = child2.genom.copy()
cxpoint1 = np.random.randint(1, size)
cxpoint2 = np.random.randint(1, size - 1)
if cxpoint2 >= cxpoint1:
cxpoint2 += 1
else:
cxpoint1, cxpoint2 = cxpoint2, cxpoint1
tmp1[cxpoint1:cxpoint2], tmp2[cxpoint1:cxpoint2] = tmp2[cxpoint1:cxpoint2].copy(), tmp1[cxpoint1:cxpoint2].copy()
new_child1 = Individual(tmp1)
new_child2 = Individual(tmp2)
return new_child1, new_child2
def mutate(children):
for child in children:
if np.random.rand() < MUTATION_PB:
child.mutate()
return children
def create_generation(POPURATIONS, GENOMS):
'''初期世代の作成
return: 個体クラスのリスト'''
generation = []
for i in range(POPURATIONS):
# individual = Individual(np.random.randint(0, 2, GENOMS))
individual = Individual(np.random.randint(0, 5, GENOMS))
generation.append(individual)
return generation
def ga_solve(generation):
'''遺伝的アルゴリズムのソルバー
return: 最終世代の最高適応値の個体、最低適応値の個体'''
best = []
worst = []
# --- Generation loop
print('Generation loop start.')
for i in range(GENERATIONS):
# --- Step1. Print fitness in the generation
best_ind = max(generation, key=Individual.get_fitness)
best.append(best_ind.fitness)
worst_ind = min(generation, key=Individual.get_fitness)
worst.append(worst_ind.fitness)
print("Generation: " + str(i) \
+ ": Best fitness: " + str(best_ind.fitness) \
+ ". Worst fitness: " + str(worst_ind.fitness))
# --- Step2. Selection (Roulette)
# selected = select_roulette(generation)
selected = select_tournament(generation)
# --- Step3. Crossover (two_point_copy)
children = crossover(selected)
# --- Step4. Mutation
generation = mutate(children)
print("Generation loop ended. The best individual: ")
print(best_ind.genom)
return best, worst
np.random.seed(seed=65)
# param
POPURATIONS = 100
# GENOMS = 50 # 江端修正
GENOMS = 160
GENERATIONS = 1000
CROSSOVER_PB = 0.8
MUTATION_PB = 0.1
# create first genetarion
generation = create_generation(POPURATIONS, GENOMS)
# solve
best, worst = ga_solve(generation)
# plot
fig, ax = plt.subplots()
ax.plot(best, label='max')
ax.plot(worst, label='min')
ax.axhline(y=GENOMS, color='black', linestyle=':', label='true')
ax.set_xlim([0, GENERATIONS - 1])
#ax.set_ylim([0, GENOMS * 1.1])
ax.set_ylim([0, GENOMS * 2.2])
ax.legend(loc='best')
ax.set_xlabel('Generations')
ax.set_ylabel('Fitness')
ax.set_title('Tournament Select')
plt.show()
明日は、この2つをマージして、目的のプログラムを完成させます。
以下のプログラムは、20個のデータを使って因子分析を行い、その分析因子分析を同じ結果を生み出す200個のダミーデータを作成します。
アルゴリズムの説明は省略します(が、私は分かっています)。
まず、データ(sample_factory.csv)
x1,x2,x3,x4,x5,x6,x7,x8
2,4,4,1,3,2,2,1
5,2,1,3,1,4,2,1
2,3,4,3,4,2,4,5
2,2,2,2,3,2,2,2
5,4,3,4,4,5,4,3
1,4,4,2,4,3,2,3
3,1,1,1,1,2,1,1
5,5,3,5,4,5,3,5
1,3,4,1,3,1,3,1
4,4,3,1,4,4,2,1
3,3,3,2,4,4,4,2
1,2,1,3,1,1,1,1
5,2,3,5,2,5,1,3
4,1,1,3,1,2,2,1
1,1,1,1,2,1,2,1
3,1,2,1,1,3,2,1
1,2,3,5,2,2,2,2
3,1,1,3,2,4,2,1
3,2,3,2,2,2,2,5
1,4,3,1,4,3,5,3
以下、GAのコード
# ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ python3 ga-factory2.py
# ライブラリのインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# import japanize_matplotlibe
from factor_analyzer import FactorAnalyzer
import matplotlib.pyplot as plt
class Individual:
'''各個体のクラス
args: 個体の持つ遺伝子情報(np.array)'''
def __init__(self, genom):
self.genom = genom
self.fitness = 0 # 個体の適応度(set_fitness関数で設定)
self.set_fitness()
def set_fitness(self):
'''個体に対する目的関数(OneMax)の値をself.fitnessに代入'''
# まずgenomを行列にデータに変換する
# self.fitness = self.genom.sum()
# 遺伝子列を行列に変換
arr2d = self.genom.reshape((-1, 8)) # 列が分からない場合は、-1にするとよい
# 各列の平均と標準偏差を計算
mean = np.mean(arr2d, axis=0)
std = np.std(arr2d, axis=0)
# 標準偏差値に変換
standardized_arr2d = (arr2d - mean) / std
# 因子分析の実行
fa_arr2d = FactorAnalyzer(n_factors=2, rotation="promax")
fa_arr2d.fit(standardized_arr2d)
# 因子分析行列の算出
loadings_arr2d = fa_arr2d.loadings_
# 因子分析行列の差分算出
distance2 = euclidean_distance(fa.loadings_, loadings_arr2d)
# print(distance2)
# とりあえず評価関数をこの辺から始めてみる
self.fitness = 1 / distance2
def get_fitness(self):
'''self.fitnessを出力'''
return self.fitness
def mutate(self):
'''遺伝子の突然変異'''
tmp = self.genom.copy()
i = np.random.randint(0, len(self.genom) - 1)
# tmp[i] = float(not self.genom[i])
tmp[i] = np.random.randint(1, 6) # 江端修正
self.genom = tmp
self.set_fitness()
def euclidean_distance(matrix_a, matrix_b):
# 行列Aと行列Bの要素ごとの差を計算します
diff = matrix_a - matrix_b
# 差の二乗を計算します
squared_diff = np.square(diff)
# 差の二乗の和を計算します
sum_squared_diff = np.sum(squared_diff)
# 和の平方根を計算します
distance = np.sqrt(sum_squared_diff)
return distance
def select_roulette(generation):
'''選択の関数(ルーレット方式)'''
selected = []
weights = [ind.get_fitness() for ind in generation]
norm_weights = [ind.get_fitness() / sum(weights) for ind in generation]
selected = np.random.choice(generation, size=len(generation), p=norm_weights)
return selected
def select_tournament(generation):
'''選択の関数(トーナメント方式)'''
selected = []
for i in range(len(generation)):
tournament = np.random.choice(generation, 3, replace=False)
max_genom = max(tournament, key=Individual.get_fitness).genom.copy()
selected.append(Individual(max_genom))
return selected
def crossover(selected):
'''交叉の関数'''
children = []
if POPURATIONS % 2:
selected.append(selected[0])
for child1, child2 in zip(selected[::2], selected[1::2]):
if np.random.rand() < CROSSOVER_PB:
child1, child2 = cross_two_point_copy(child1, child2)
children.append(child1)
children.append(child2)
children = children[:POPURATIONS]
return children
def cross_two_point_copy(child1, child2):
'''二点交叉'''
size = len(child1.genom)
tmp1 = child1.genom.copy()
tmp2 = child2.genom.copy()
cxpoint1 = np.random.randint(1, size)
cxpoint2 = np.random.randint(1, size - 1)
if cxpoint2 >= cxpoint1:
cxpoint2 += 1
else:
cxpoint1, cxpoint2 = cxpoint2, cxpoint1
tmp1[cxpoint1:cxpoint2], tmp2[cxpoint1:cxpoint2] = tmp2[cxpoint1:cxpoint2].copy(), tmp1[cxpoint1:cxpoint2].copy()
new_child1 = Individual(tmp1)
new_child2 = Individual(tmp2)
return new_child1, new_child2
def mutate(children):
for child in children:
if np.random.rand() < MUTATION_PB:
child.mutate()
return children
def create_generation(POPURATIONS, GENOMS):
'''初期世代の作成
return: 個体クラスのリスト'''
generation = []
for i in range(POPURATIONS): # POPURATIONS = 100
# individual = Individual(np.random.randint(0, 2, GENOMS))
individual = Individual(np.random.randint(1, 6, GENOMS))
generation.append(individual)
return generation
def ga_solve(generation):
'''遺伝的アルゴリズムのソルバー
return: 最終世代の最高適応値の個体、最低適応値の個体'''
best = []
worst = []
# --- Generation loop
print('Generation loop start.')
for i in range(GENERATIONS):
# --- Step1. Print fitness in the generation
best_ind = max(generation, key=Individual.get_fitness)
best.append(best_ind.fitness)
worst_ind = min(generation, key=Individual.get_fitness)
worst.append(worst_ind.fitness)
print("Generation: " + str(i) \
+ ": Best fitness: " + str(best_ind.fitness) \
+ ". Worst fitness: " + str(worst_ind.fitness))
# --- Step2. Selection (Roulette)
# selected = select_roulette(generation)
selected = select_tournament(generation)
# --- Step3. Crossover (two_point_copy)
children = crossover(selected)
# --- Step4. Mutation
generation = mutate(children)
print("Generation loop ended. The best individual: ")
print(best_ind.genom)
return best, worst
np.random.seed(seed=65)
# param
POPURATIONS = 100 # 個体数
# GENOMS = 50 # 江端修正
# GENOMS = 160 # GENの長さ
GENOMS = 1600 # GENの長さ 1つのデータが8個の整数からなるので、合計200個のデ0タとなる
GENERATIONS = 1000
CROSSOVER_PB = 0.8
# MUTATION_PB = 0.1
MUTATION_PB = 0.3 # ミューテーションは大きい方が良いように思える
# ファイルからデータの読み込み
df_workers = pd.read_csv("sample_factor.csv")
print(df_workers)
# 変数の標準化
df_workers_std = df_workers.apply(lambda x: (x-x.mean())/x.std(), axis=0)
print(df_workers_std)
# 固有値を求める(不要と思うけど、残しておく)
ei = np.linalg.eigvals(df_workers.corr())
print(ei)
print("因子分析の実行") # 絶対必要
fa = FactorAnalyzer(n_factors=2, rotation="promax")
fa.fit(df_workers_std)
# print(fa.loadings_) # これが因子分析の行列
# 因子負荷量,共通性(不要と思うけど、残しておく)
loadings_df = pd.DataFrame(fa.loadings_, columns=["第1因子", "第2因子"])
loadings_df.index = df_workers.columns
loadings_df["共通性"] = fa.get_communalities()
# 因子負荷量の二乗和,寄与率,累積寄与率(不要と思うけど、残しておく)
var = fa.get_factor_variance()
df_var = pd.DataFrame(list(zip(var[0], var[1], var[2])),
index=["第1因子", "第2因子"],
columns=["因子負荷量の二乗和", "寄与率", "累積寄与率"])
print(df_var.T)
# create first genetarion
generation = create_generation(POPURATIONS, GENOMS)
# solve
best, worst = ga_solve(generation)
# plot
#fig, ax = plt.subplots()
#ax.plot(best, label='max')
#ax.plot(worst, label='min')
#ax.axhline(y=GENOMS, color='black', linestyle=':', label='true')
#ax.set_xlim([0, GENERATIONS - 1])
#ax.set_ylim([0, GENOMS * 1.1])
#ax.legend(loc='best')
#ax.set_xlabel('Generations')
#ax.set_ylabel('Fitness')
#ax.set_title('Tournament Select')
#plt.show()
ga-factory2.py :200固体 主成分行列からの距離は、distance2(これが一致度) 評価関数は、この逆数を使っているだけ
ga-factory3.py :2000固体
以上
【QGIS】緯度・経度をもつCSVデータを読み込み、地図に表示する
【QGIS】緯度・経度をもつCSVデータを読み込み、地図に表示する
Lat, Lng
35.3663 , 139.6225
35.3669 , 139.6245
35.3673 , 139.6259
35.3672 , 139.6268
35.3673 , 139.6296
35.3668 , 139.6296
35.367 , 139.6296
35.3671 , 139.6297
35.3672 , 139.6298
35.368 , 139.622(以下、省略)
(2)CSVファイルの読み込み
(3)結果
以上
街の中に道路を作って、ダイクストラ計算ができるか試してみた件 ―― JOSMを使った道路追加の方法を試す
この投稿の最後に書いた『経路が繋がっていないと、ダイクストラ計算はできないはずなので』を、JOSMを使ってなんとかできないか実験中しています。
で、こちらの本で例題として出している街のデータを使って実験します(宇都宮のデータはデカすぎるので)。
https://github.com/TomoichiEbata/hirohakama/tree/main/hiro_db の hirohakama.osmを使って実験します。
まず、hirohakama.osm から hirohakama1.osmを複製して、さらに、このhirohakama1.osmを、JOSMにローディングして、ファイル → 保存をします。JOSMに入れるだけで、フォーマットの一部が変更されるからです。
こうしておいて、さらに、hirohakama1.osmのコピー、hirohakama2.osmを作成します。
以後、この2つのファイルを比較することで、作成状況を把握していきたいと思います。
まず、すでにあるノード(node)間を繋いで道路を作ってみます。(小さい□がnodeです)
をクリックして、
この2点間に線を引きます。
で、その後、このhirohakama2.osmをセーブして、hirohakama1.osmと比較してみました。
結果は以下の通り。way id='220736115' に、ref='3813457320'のノードが追加されています(この一行だけ)。
ちなみに、ref='3813457320'のノードの情報は、
<node id='3813457320' timestamp='2015-11-02T07:07:06Z' uid='3057995' user='oini' visible='true' version='1' changeset='35026994' lat='35.5957559' lon='139.4735283' />
となっています。
既存のノード同士をくっ付けるのであれば、結構簡単にできそうです。
では、ノード以外の道路を適当に繋げるとどうなるかを、調べてみます。
で、ノード番号 -101965, -101966 の座標は入っていませんでした(作られていませんでした)。多分ダイクストラやっても、無視されると思います。
見落していました。作られていました(ファイルの最初の方だったので)。
<node id='-101792' action='modify' visible='true' lat='35.59604489421' lon='139.47307912887' />
<node id='-101793' action='modify' visible='true' lat='35.59558383511' lon='139.47265061383' />
ノードを動かしたら、
ちゃんと、ノードの座標も動いていました。
ただ、ノードでない場所(×の部分)とかを動かしてノードを増やしても、先程のようにマイナスのノード番号が出てきて、座標も追加されませんでした。
しかし、ノードの追加はしたいなぁ(今後のことを考えると)
で、"JOSM" "ノードの追加" で検索したら、このページが出てきました。
しかし、ただノードを追加すれば良いってもんじゃない。既存のWAYに埋め込まなれば意味がない。さて、どうしようか。
今考えている、最も安直なアイデアは、
OSMファイルに、ノード番号 -101965, -101966 の座標を手で書き込む、です。
試してみて、上手くいったら、またご報告します。
不要です。座標(ノード)はできていました。現時点の問題は、QGISとかに表示されない、ということです。
私が、人工的に追加したノードの記述は、
<node id='-101792' action='modify' visible='true' lat='35.59604489421' lon='139.47307912887' />
ですが、オリジナルのノードは、
<node id='278288868' timestamp='2015-11-02T07:00:53Z' uid='3057995' user='oini' visible='true' version='4' changeset='35026937' lat='35.5997134' lon='139.4660138' />
と、だいぶ表示形式が違うようです。
JOSMでは表示されますが、QGISでは表示されません。
に、
JOSMは、どの要素が変更されたかを正確に記録しています。アップロード時には、あなたが触っていないオブジェクトはすべて無視されます。タグを追加して後で削除した場合など、例外があるかもしれません。
この情報はOSM XMLファイルにも保存されます。action='modify' と action='delete' の要素だけが、OSM データベースにアップロードされます。
との記載がありました。つまり、本番情報として認識されないのかな、と思っています。
https://wiki.openstreetmap.org/wiki/JA:%E3%83%8E%E3%83%BC%E3%83%89
には、
名前 | 値 | 説明 |
---|---|---|
id | 整数(>=1) | ノードのIDはノードの中でのみ一意となる。(同じIDを持つウェイが存在しても良い。)一般的なエディターでは、サーバーに保存される前のノードのIDに負数が用いられる。サーバー上のノードのIDは不変であり、既存のノードに割り当てられたIDは将来にわたって変更されない。削除されたノードのIDが最利用されることはない(削除を取り消した場合を除く)。 |
という記載があるので、少なくとも負数を使うのは、ダメみたい。
近くにある、このNodeとWayを参照してみる。
(宇都宮レールウェイの場合)<tag k='construction' v='tram'/>と記載されていましたので、これを、強制的に<tag k='railway' v='tram'/>に置換する
(1)node id, way idの負数から、マイナスを取って、強制的に正数にする(他のnodeやwayとぶつかっていないことを確認する)
(2)"action='modify'" を削除してみる
(2)<tag k='highway' v='residential' />を追加してみる。
<way id='102395' visible='true'>
<nd ref='101792' />
<nd ref='101793' />
<tag k='highway' v='residential' />
</way>
で、これでQGISで表示したら、やっと出てきました。
この、手動で変更したhirohakama-21.osmが、postgreSQL+postGISに載るかやってみました。
詳しい手続は、このWebサイトから探していただくか、面倒なら、GISをDIYで作ろう―PostGISを使い倒すを手に入れて下さい。
root@abbab13a933e:/# psql -U postgres
psql (12.5 (Debian 12.5-1.pgdg100+1))
Type "help" for help.postgres=# CREATE DATABASE hiro_db21;
CREATE DATABASE
postgres=# \c hiro_db21
You are now connected to database "hiro_db21" as user "postgres".
hiro_db21=# create extension postgis;
CREATE EXTENSION
hiro_db21=# create extension pgrouting;
CREATE EXTENSIONhiro_db21=# \dt
List of relations
Schema | Name | Type | Owner
--------+-----------------+-------+----------
public | spatial_ref_sys | table | postgres
(1 row)hiro_db21=# exit
root@abbab13a933e:/# osm2pgrouting -f /hiro_db/hirohakama-21.osm -c /usr/local/share/osm2pgrouting/mapconfig_for_cars.xml -d hiro_db21 -U postgres
さて、ダイクストラがちゃんと働いているかを調べてみました。
hiro_db21=# SELECT seq, node, edge, cost FROM pgr_dijkstra('SELECT gid as id,
source, target,length as cost, reverse_cost FROM ways',31, 262);
seq | node | edge | cost
-----+------+------+------------------------
1 | 31 | 1 | 0.0002245334340526014
2 | 1 | 3 | 0.000629444702259577
3 | 2 | 356 | 0.00046326006156789223
4 | 262 | -1 | 0
(4 rows)
QGISで調べてみました。
新しい道路で、ダイクストラ計算ができていることが確認できました。
P.S. 調べていたら、駅の構成についての説明文を見つけました。後程、参考にさせて貰おうと思います。
万人に共通に使いやすい注文システムの究極は ―― 『タブレットを使わない、口頭でのオーダー』、つまり従来通りです。
多くの飲食店で、テーブルに備えつけられたタブレットからメニューをオーダーするシステムが、導入されています。
Many restaurants have installed systems allowing customers to order tablet menu items at each table.
今や、そういうシステムがない店舗の方が珍しいくらいです。
Nowadays, finding a restaurant without such a system is so rare.
最低賃金が上がり、人不足が深刻な中、これは当然の流れと言えます。
This is a natural trend, with minimum wages rising and a severe labor shortage.
ただ、言うまでもないのですが、これらのタブレットのインターフェースは、『絶望的なまでに使いにくい』。
But needless to say, the interface of these tablets is 'hopelessly difficult to use.
『このタブレットのインターフェースを設計しているヤツは、バカなのか』と思います ―― かなり本気で。
I think, 'Are the people designing this tablet interface stupid?' -- quite seriously.
しかし、面倒なので、このインターフェースについての批判は割愛します。
However, since it is tedious, I will omit the criticism of this interface.
-----
万人に共通に使いやすい注文システムの究極は ―― 『タブレットを使わない、口頭でのオーダー』、つまり従来通りです。
The ultimate ordering system that is easy for everyone is -- "no tablets, verbal orders," in other words, the same as before.
ですので、現在のタブレット注文システムが、「音声入力」と「生成AI」からなる、音声による自動オーダシステムになっていくことは、ほぼ確実です。
Therefore, it is almost certain that the current tablet ordering system will be replaced by an automated voice-based ordering system consisting of "voice input" and "generated AI.
近い未来、『音声入力生成AIと客が、オーダーの違いで、口論になる』という場面を見られるようになるでしょう。
We will soon see voice input generation AI and customers arguing over different orders.
そして、100%完全録音された会話によって、多くの場合、『客の過失(オーダーのミス)が、簡単に確認される』ということになるでしょう。
And, in many cases, a 100% fully recorded conversation will 'easily confirm the customer's negligence (mistake in ordering).
-----
気になるのは、その開始時期です。
What is of interest is the timing of its service-in.
私は、年内に登場、来年はトライアル期間、再来年あたりには飲食業界では普通になる、という気がしています。
They will appear by the end of the year; next year will be a trial period, and around the year after that, they will become the norm in the food and beverage industry.
ssh 192.168.0.232でログインしようとしたのですが、ユーザIDを聞いてこずに、いきなりパスワードを聞かれてログインに失敗しました。どうすれば良いでしょうか
ssh ユーザID@192.168.0.232