UVa 10798 Be Wary of Roses

题目描述

你为自己的获奖玫瑰园感到自豪,但嫉妒的园丁绑架了你,把你蒙住眼睛、戴上手铐扔在了玫瑰园的正中央!你站在一个方形大理石基座上,这个基座位于 N×NN \times NN×N 网格(NNN 为奇数)的正中心。你不知道自己面朝哪个方向,但可以确定自己面向北、东、南、西四个基本方向之一。

你必须设计一条逃生路径,使得无论初始面朝哪个方向,沿着这条路径走(根据实际方向调整移动方向)所踩到的玫瑰数量都尽可能少。路径必须从中心开始,只包含水平和垂直移动,最终要走出网格边界。

输入格式

  • 每个测试用例以整数 NNN1≤N≤211 \le N \le 211N21NNN 为奇数)开始
  • 接下来 NNN 行,每行 NNN 个字符,描述花园布局:
    • . 表示空地
    • R 表示玫瑰
    • P 表示中心基座
  • 输入以 N=0N = 0N=0 结束

输出格式

对于每个测试用例,输出一行:At most X rose(s) trampled.,其中 XXX 是保证能踩到的最少玫瑰数。

题目分析与解题思路

问题本质

这个问题需要我们在不知道初始方向的情况下设计一条路径。关键观察是:虽然我们不知道初始方向,但四个可能的初始方向(北、东、南、西)是对称的。如果我们设计一条指令序列(如前、左、右等),那么在四个不同初始方向下执行这个序列,会得到四条不同的路径,但这些路径之间存在旋转对称关系。

对称性利用

设我们在第一象限(以中心为原点)走的路径为一系列移动。那么对于初始方向:

  • :直接按路径走
  • :路径顺时针旋转 90∘90^\circ90
  • :路径旋转 180∘180^\circ180
  • 西:路径逆时针旋转 90∘90^\circ90

因此,我们只需要搜索第一象限的路径,其他三个方向的路径可以通过旋转得到。这大大减少了搜索空间。

基础思路:朴素 DFS\texttt{DFS}DFS

解题思路

最直接的想法是使用深度优先搜索(DFS\texttt{DFS}DFS)探索所有可能的路径。我们只在一个方向上(比如第一象限)搜索路径,然后通过对称性计算其他三个方向的对应路径。在搜索过程中,我们记录四个方向上各自踩到的玫瑰数,并跟踪当前最优解。

算法框架
  1. 状态表示:当前位置 (x,y)(x, y)(x,y),四个方向已踩玫瑰数数组 roses[4]\texttt{roses}[4]roses[4]
  2. 搜索过程:从中心点开始,每次尝试向四个方向移动一步
  3. 对称性处理:对于每个移动,计算四个旋转方向对应的实际位置
  4. 剪枝策略:如果当前四个方向的最大玫瑰数已经不小于当前最优解,则放弃该分支
  5. 终止条件:到达网格边界时更新最优解
代码实现
// Be Wary of Roses
// UVa ID: 10798
// Verdict: Accepted
// Submission Date: 2025-12-23
// UVa Run Time: 1.520s
//
// 版权所有(C)2025,邱秋。metaphysis # yeah dot net

#include <bits/stdc++.h>
using namespace std;

int n;
string grid[32];
int bestAnswer;
int dx[4] = {0, 1, -1, 0}, dy[4] = {1, 0, 0, -1};
int visited[32][32], roses[4];

void dfs(int x, int y) {
    // 检查路径是否在边界上,已在边界上则更新答案
    if (x == 0 || y == 0 || x == n - 1 || y == n - 1) {
        bestAnswer = min(bestAnswer, *max_element(roses, roses + 4));
        return;
    }
    // 尝试四个方向移动
    for (int d = 0; d < 4; d++) {
        int newX = x + dx[d], newY = y + dy[d];
        if (newX < 0 || newX >= n || newY < 0 || newY >= n) continue;
        if (visited[newX][newY]) continue;
        for (int i = 0; i < 4; i++) {
            int xx = newX, yy = newY;
            if (i == 1) { xx = newY; yy = n - 1 - newX; }
            if (i == 2) { xx = n - 1 - newX; yy = n - 1 - newY; }
            if (i == 3) { xx = n - 1 - newY; yy = newX; }
            roses[i] += grid[xx][yy] == 'R';
        }
        // 剪枝
        if (*max_element(roses, roses + 4) < bestAnswer) {
            visited[newX][newY] = true;
            dfs(newX, newY);
            visited[newX][newY] = false;
        }
        for (int i = 0; i < 4; i++) {
            int xx = newX, yy = newY;
            if (i == 1) { xx = newY; yy = n - 1 - newX; }
            if (i == 2) { xx = n - 1 - newX; yy = n - 1 - newY; }
            if (i == 3) { xx = n - 1 - newY; yy = newX; }
            roses[i] -= grid[xx][yy] == 'R';
        }
    }
}

int main() {
    cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
    while (cin >> n && n) {
        for (int i = 0; i < n; i++) cin >> grid[i];
        // 先直走,确定一个初始最优值
        bestAnswer = 0;
        for (int i = 0; i < 4; i++) {
            int cnt = 0, x = n / 2, y = n / 2;
            while (true) {
                x += dx[i], y += dy[i];
                if (x < 0 || x >= n || y < 0 || y >= n) break;
                cnt += grid[x][y] == 'R';
            }
            bestAnswer = max(bestAnswer, cnt);
        }
        memset(roses, 0, sizeof roses);
        memset(visited, 0, sizeof visited);
        visited[n / 2][n / 2] = 1;
        dfs(n / 2, n / 2);
        cout << "At most " << bestAnswer << " rose(s) trampled.\n";
    }
    return 0;
}
算法分析
  • 时间复杂度:指数级,最坏情况下需要探索所有可能的路径
  • 空间复杂度O(N2)O(N^2)O(N2),主要用于访问标记数组
  • 运行时间1520ms1520 \texttt{ms}1520ms(在评测系统中)
  • 优点:实现简单直观,易于理解
  • 缺点:效率较低,搜索空间大,仅适用于小规模问题
存在的问题

朴素 DFS\texttt{DFS}DFS 虽然能够解决问题,但由于搜索空间呈指数增长,当网格尺寸较大时效率很低。我们需要更高效的剪枝策略来减少不必要的搜索。


优化思路:启发式剪枝 DFS\texttt{DFS}DFS

解题思路

为了加速搜索过程,我们引入启发式剪枝。核心思想是:预处理每个位置到边界的最少玫瑰数,作为从该位置到边界的下界估计。在搜索过程中,如果当前某个方向已踩玫瑰数加上从该位置到边界的最少玫瑰数已经不小于当前最优解,那么这个分支不可能产生更好的解,可以剪枝。

算法改进
  1. 预处理阶段:使用 BFS\texttt{BFS}BFS 从边界向内传播,计算 minRoses[x][y]\texttt{minRoses}[x][y]minRoses[x][y],表示从位置 (x,y)(x, y)(x,y) 到任意边界的最少玫瑰数
  2. 启发式剪枝:对于每个方向 iii,如果 roses[i]+minRoses[xx][yy]≥bestAnswer\texttt{roses}[i] + \texttt{minRoses}[xx][yy] \ge \texttt{bestAnswer}roses[i]+minRoses[xx][yy]bestAnswer,则剪枝
  3. 更精细的状态管理:将四个方向的玫瑰计数更新合并到一次循环中,减少重复计算
代码实现
// Be Wary of Roses
// UVa ID: 10798
// Verdict: Accepted
// Submission Date: 2025-12-23
// UVa Run Time: 0.240s
//
// 版权所有(C)2025,邱秋。metaphysis # yeah dot net

#include <bits/stdc++.h>
using namespace std;

int n;
string grid[32];
int bestAnswer;
int dx[4] = {0, 1, -1, 0}, dy[4] = {1, 0, 0, -1};
int minRoses[32][32];
int visited[32][32], roses[4];

// 预计算从边界到某个位置踩下的最少玫瑰数量作为启发式剪枝
void bfs() {
    memset(minRoses, 0x3f, sizeof minRoses);
    queue<pair<int, int>> q;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {
                minRoses[i][j] = (grid[i][j] == 'R') ? 1 : 0;
                q.push({i, j});
            }
    while (!q.empty()) {
        pair<int, int> xy = q.front(); q.pop();
        for (int d = 0; d < 4; d++) {
            int nx = xy.first + dx[d], ny = xy.second + dy[d];
            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
            if (grid[nx][ny] == 'P') continue;
            int v = minRoses[xy.first][xy.second] + ((grid[nx][ny] == 'R') ? 1 : 0);
            if (v < minRoses[nx][ny]) {
                minRoses[nx][ny] = v;
                q.push({nx, ny});
            }
        }
    }
}

void dfs(int x, int y) {
    // 检查路径是否在边界上,已在边界上则更新答案
    if (x == 0 || y == 0 || x == n - 1 || y == n - 1) {
        bestAnswer = min(bestAnswer, *max_element(roses, roses + 4));
        return;
    }
    // 尝试四个方向移动
    int tmp[4];
    for (int d = 0; d < 4; d++) {
        int newX = x + dx[d], newY = y + dy[d];
        if (newX < 0 || newX >= n || newY < 0 || newY >= n) continue;
        if (visited[newX][newY]) continue;
        bool valid = true;
        for (int i = 0; i < 4; i++) {
            // 利用对称性获取四条路径要走的下一个位置
            int xx = newX, yy = newY;
            if (i == 1) { xx = newY; yy = n - 1 - newX; }
            if (i == 2) { xx = n - 1 - newX; yy = n - 1 - newY; }
            if (i == 3) { xx = n - 1 - newY; yy = newX; }
            // 检查要走的位置是否有玫瑰
            tmp[i] = grid[xx][yy] == 'R';
            // 剪枝
            // 从当前位置到边界至少还需要踩下的玫瑰数量加上到达当前位置已经踩下的玫瑰数量,
            // 如果该数量大于等于最优值,则该条路径可以放弃继续搜索
            if (roses[i] + minRoses[xx][yy] >= bestAnswer) {
                valid = false;
                break;
            }
        }
        if (!valid) continue;
        for (int i = 0; i < 4; i++) roses[i] += tmp[i];
        visited[newX][newY] = true;
        dfs(newX, newY);
        visited[newX][newY] = false;
        for (int i = 0; i < 4; i++) roses[i] -= tmp[i];
    }
}

int main() {
    cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
    while (cin >> n && n) {
        for (int i = 0; i < n; i++) cin >> grid[i];
        // 确定从边界到任意一个位置至少需要踩下多少玫瑰
        bfs();
        // 先直走,确定一个初始最优值
        bestAnswer = 0;
        for (int i = 0; i < 4; i++) {
            int cnt = 0, x = n / 2, y = n / 2;
            while (true) {
                x += dx[i], y += dy[i];
                if (x < 0 || x >= n || y < 0 || y >= n) break;
                cnt += grid[x][y] == 'R';
            }
            bestAnswer = max(bestAnswer, cnt);
        }
        memset(roses, 0, sizeof roses);
        memset(visited, 0, sizeof visited);
        visited[n / 2][n / 2] = 1;
        dfs(n / 2, n / 2);
        cout << "At most " << bestAnswer << " rose(s) trampled.\n";
    }
    return 0;
}
算法分析
  • 时间复杂度:预处理 O(N2)O(N^2)O(N2),搜索过程因剪枝大幅减少
  • 空间复杂度O(N2)O(N^2)O(N2),增加了 minRoses\texttt{minRoses}minRoses 数组
  • 运行时间240ms240 \texttt{ms}240ms,效率提升约 666
  • 优点:剪枝效果显著,效率高,实现相对简单
  • 缺点:启发式函数可能不够紧,仍可能搜索不必要分支
进一步优化空间

虽然启发式剪枝显著提升了效率,但我们仍然可能搜索许多不会产生更优解的状态。一个自然的想法是:能否系统地、按最优性顺序探索状态,而不是依赖深度优先的顺序?


高级思路:优先队列 BFS\texttt{BFS}BFS 与状态记忆化

解题思路

我们采用优先队列 BFS\texttt{BFS}BFS(类似 Dijkstra\texttt{Dijkstra}Dijkstra 算法)的策略,按当前最坏情况玫瑰数从小到大扩展状态。这样可以保证首次找到的解就是最优解。同时,我们使用六维状态记忆化避免重复搜索相同状态。

算法设计
  1. 状态定义(x,y,l,u,r,d)(x, y, l, u, r, d)(x,y,l,u,r,d),其中:
    • (x,y)(x, y)(x,y):第一象限路径的当前位置(绝对坐标)
    • l,u,r,dl, u, r, dl,u,r,d:四个方向(北、东、南、西)已踩的玫瑰数
  2. 优先队列:按 max⁡(l,u,r,d)\max(l, u, r, d)max(l,u,r,d) 从小到大排序
  3. 状态记忆化visited[x][y][l][u][r][d]\texttt{visited}[x][y][l][u][r][d]visited[x][y][l][u][r][d] 记录已访问状态
  4. 扩展策略:每次从队列取出最坏情况最小的状态,尝试四个方向移动
  5. 终止条件:当尝试移动到网格外时,返回当前状态的最大玫瑰数
代码实现
// Be Wary of Roses
// UVa ID: 10798
// Verdict: Accepted
// Submission Date: 2025-12-23
// UVa Run Time: 0.270s
//
// 版权所有(C)2025,邱秋。metaphysis # yeah dot net

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 24, MAXM = 12;
int offset[4][2] = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};

struct state {
    int x, y, l, u, r, d, w;
    state (int x = 0, int y = 0, int l = 0, int u = 0, int r = 0, int d = 0): x(x), y(y), l(l), u(u), r(r), d(d) {
        w = max(max(l, r), max(u, d));
    }
    bool operator<(const state& s) const { return w > s.w; }
};

int n, visited[MAXN][MAXN][MAXM][MAXM][MAXM][MAXM];
string g[MAXN];

int bfs (int x, int y) {
    memset(visited, 0, sizeof(visited));
    priority_queue<state> q;
    visited[x][y][0][0][0][0] = 1;
    q.push(state(x, y, 0, 0, 0, 0));
    while (!q.empty()) {
        state current = q.top(); q.pop();
        for (int i = 0; i < 4; i++) {
            state nxt = current;
            int x = current.x + offset[i][0], y = current.y + offset[i][1];
            if (x < 0 || x >= n || y < 0 || y >= n) return current.w;
            nxt.x = x, nxt.y = y;
            if (g[x][y] == 'R') nxt.l++;
            if (g[y][n - 1 - x] == 'R') nxt.u++;
            if (g[n - 1 - x][n - 1 - y] == 'R') nxt.r++;
            if (g[n - 1 - y][x] == 'R') nxt.d++;
            if (visited[x][y][nxt.l][nxt.u][nxt.r][nxt.d]) continue;
            visited[x][y][nxt.l][nxt.u][nxt.r][nxt.d] = 1;
            q.push(state(x, y, nxt.l, nxt.u, nxt.r, nxt.d));
        }
    }
    return -1;
}

int main () {
    cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
    while (cin >> n && n) {
        for (int i = 0; i < n; i++) cin >> g[i];
        cout << "At most " << bfs(n / 2, n / 2) << " rose(s) trampled.\n";
    }
    return 0;
}
旋转公式的数学推导

代码中的旋转计算基于以下坐标变换(假设网格索引从 000 开始):

  • 北(0∘0^\circ0):(x,y)(x, y)(x,y)
  • 东(90∘90^\circ90):(y,n−1−x)(y, n-1-x)(y,n1x)
  • 南(180∘180^\circ180):(n−1−x,n−1−y)(n-1-x, n-1-y)(n1x,n1y)
  • 西(270∘270^\circ270):(n−1−y,x)(n-1-y, x)(n1y,x)

这些变换确保了四个路径关于中心点的对称性。

算法分析
  • 时间复杂度O(N2×R4)O(N^2 \times R^4)O(N2×R4),其中 RRR 是最大玫瑰数(约 101010
  • 空间复杂度O(N2×R4)O(N^2 \times R^4)O(N2×R4),六维状态数组
  • 运行时间240ms240 \texttt{ms}240ms,与启发式剪枝 DFS\texttt{DFS}DFS 相当
  • 优点:保证找到最优解,逻辑清晰,无过度剪枝风险
  • 缺点:状态空间大,内存消耗较高,实现稍复杂
状态空间分析

对于 N=21N=21N=21,每个坐标维度有 212121 种可能,每个玫瑰数维度最多 111111 种可能(0−100-10010),总状态数约为:
21×21×11×11×11×11≈6.5×10621 \times 21 \times 11 \times 11 \times 11 \times 11 \approx 6.5 \times 10^621×21×11×11×11×116.5×106
这在现代计算机上是可接受的。


算法对比与总结

三种算法对比表

算法核心思想时间复杂度空间复杂度运行时间优点缺点
朴素 DFS\texttt{DFS}DFSDFS\texttt{DFS}DFS + 基本剪枝指数级O(N2)O(N^2)O(N2)1520ms1520 \texttt{ms}1520ms实现简单,直观易懂效率低,搜索空间大
启发式 DFS\texttt{DFS}DFSDFS\texttt{DFS}DFS + 下界估计剪枝指数级(大幅剪枝)O(N2)O(N^2)O(N2)240ms240 \texttt{ms}240ms剪枝高效,实现相对简单可能剪枝不足或过度
优先队列 BFS\texttt{BFS}BFSBFS\texttt{BFS}BFS + 状态记忆化O(N2R4)O(N^2 R^4)O(N2R4)O(N2R4)O(N^2 R^4)O(N2R4)240ms240 \texttt{ms}240ms保证最优性,逻辑清晰状态空间大,内存消耗高

关键解题技巧总结

  1. 对称性利用:将四方向问题简化为单方向搜索,是本题的核心优化
  2. 搜索策略选择
    • DFS\texttt{DFS}DFS 适合结合强力剪枝
    • 优先队列 BFS\texttt{BFS}BFS 适合保证最优性
  3. 剪枝策略
    • 简单剪枝:比较当前最优解
    • 启发式剪枝:使用下界估计
  4. 状态设计:合理的状态表示可以避免重复搜索

推荐算法

对于本题,推荐使用第二种算法(启发式剪枝 DFS\texttt{DFS}DFS,原因如下:

  1. 效率高240ms240 \texttt{ms}240ms的运行时间完全满足要求
  2. 实现简单:相对于优先队列 BFS\texttt{BFS}BFS 的六维状态,DFS\texttt{DFS}DFS 实现更直观
  3. 内存友好:不需要存储大量状态,内存消耗小
  4. 稳定可靠:在实际评测中表现稳定

扩展思考

  1. 能否进一步优化?可以考虑结合 A*\texttt{A*}A* 搜索,使用更精确的启发函数
  2. 更大规模的问题:如果 NNN 更大,可能需要更高效的剪枝或近似算法
  3. 实际问题应用:这种对称性搜索技巧可以应用于许多机器人路径规划问题

总结

本题是一道经典的搜索优化问题,通过分析三种不同的解题思路,我们看到了算法设计的演进过程:从朴素搜索到启发式剪枝,再到系统性的优先队列搜索。每种方法都有其适用场景和优缺点,理解这些差异有助于我们在解决类似问题时选择最合适的策略。

这道题不仅考察了搜索算法的实现能力,更重要的是考察了对问题对称性的洞察力和剪枝策略的设计能力。掌握这些技巧对于解决竞赛中的搜索优化问题至关重要。

geo_model.set_active_grids,from gempy.core.data import Surfaced在我的gempy中没有这些功能,我的gempy信息如下:F:\pythonProject\gempy-main.venv\Scripts\python.exe F:\pycharm\3d1.py Setting Backend To: AvailableBackends.numpy Help on package gempy_viewer: NAME gempy_viewer PACKAGE CONTENTS API (package) DEP (package) _version core (package) modules (package) optional_dependencies FUNCTIONS plot_2d(model: gempy.core.data.geo_model.GeoModel, n_axis=None, section_names: list = None, cell_number: Union[int, list[int], str, list[str], NoneType] = None, direction: Union[str, list[str], NoneType] = 'y', series_n: Union[int, List[int]] = 0, legend: bool = True, ve=1, block=None, override_regular_grid=None, kwargs_topography=None, kwargs_lithology=None, kwargs_scalar_field=None, **kwargs) -> gempy_viewer.modules.plot_2d.visualization_2d.Plot2D Plot 2-D sections of the geomodel. This function plots cross-sections either based on custom section traces or cell numbers in the xyz directions. Options are provided to plot lithology blocks, scalar fields, or rendered surface lines. Input data and topography can be included. Args: model (GeoModel): Geomodel object with solutions. n_axis (Optional[int]): Subplot axis for multiple sections. section_names (Optional[List[str]]): Names of predefined custom section traces. cell_number (Optional[Union[int, List[int], str, List[str]]]): Position of the array to plot. direction (Optional[Union[str, List[str]]]): Cartesian direction to be plotted (xyz). series_n (Union[int, List[int]]): Number of the scalar field. legend (bool): If True, plot legend. Defaults to True. ve (float): Vertical exaggeration. Defaults to 1. block (Optional[np.ndarray]): Deprecated. Use regular grid instead. override_regular_grid (Optional[np.ndarray]): Numpy array of the size of model.grid.regular_grid. If provided, the regular grid will be overridden by this array. kwargs_topography (Optional[dict]): Additional keyword arguments for topography. * fill_contour: Fill contour flag. * hillshade (bool): Calculate and add hillshading using elevation data. * azdeg (float): Azimuth of sun for hillshade. - altdeg (float): Altitude in degrees of sun for hillshade. kwargs_lithology (Optional[dict]): Additional keyword arguments for lithology. kwargs_scalar_field (Optional[dict]): Additional keyword arguments for scalar field. Keyword Args: show_block (bool): If True and the model has been computed, plot cross section of the final model. show_values (bool): If True and the model has been computed, plot cross section of the value. show (bool): Call matplotlib show. Defaults to True. show_data (bool): Show original input data. Defaults to True. show_results (bool): If False, override show lithology, scalar field, and values. Defaults to True. show_lith (bool): Show lithological block volumes. Defaults to True. show_scalar (bool): Show scalar field isolines. Defaults to False. show_boundaries (bool): Show surface boundaries as lines. Defaults to True. show_topography (bool): Show topography on plot. Defaults to False. show_section_traces (bool): Show section traces. Defaults to True. Returns: gempy.plot.visualization_2d.Plot2D: Plot2D object. plot_3d(model: gempy.core.data.geo_model.GeoModel, plotter_type: str = 'basic', active_scalar_field: Optional[str] = None, ve: Optional[float] = None, topography_scalar_type: gempy_viewer.core.scalar_data_type.TopographyDataType = <TopographyDataType.GEOMAP: 2>, kwargs_pyvista_bounds: Optional[dict] = None, kwargs_plot_structured_grid: Optional[dict] = None, kwargs_plot_topography: Optional[dict] = None, kwargs_plot_data: Optional[dict] = None, kwargs_plotter: Optional[dict] = None, kwargs_plot_surfaces: Optional[dict] = None, image: bool = False, show: bool = True, transformed_data: bool = False, **kwargs) -> gempy_viewer.modules.plot_3d.vista.GemPyToVista Plot 3-D geomodel. Args: model (GeoModel): Geomodel object with solutions. plotter_type (str): Type of plotter to use. Defaults to 'basic'. active_scalar_field (Optional[str]): Active scalar field for the plot. ve (Optional[float]): Vertical exaggeration. topography_scalar_type (TopographyDataType): Type of topography scalar data. Defaults to TopographyDataType.GEOMAP. kwargs_pyvista_bounds (Optional[dict]): Additional keyword arguments for PyVista bounds. kwargs_plot_structured_grid (Optional[dict]): Additional keyword arguments for plotting the structured grid. kwargs_plot_topography (Optional[dict]): Additional keyword arguments for plotting the topography. kwargs_plot_data (Optional[dict]): Additional keyword arguments for plotting data. kwargs_plotter (Optional[dict]): Additional keyword arguments for the plotter. kwargs_plot_surfaces (Optional[dict]): Additional keyword arguments for plotting surfaces. image (bool): If True, saves the plot as an image. Defaults to False. show (bool): If True, displays the plot. Defaults to True. transformed_data (bool): If True, uses transformed data for plotting. Defaults to False. **kwargs: Additional keyword arguments. Returns: GemPyToVista: Object for 3D plotting in GemPy. plot_section_traces(model: gempy.core.data.geo_model.GeoModel, section_names: list[str] = None) Plot section traces of section grid in 2-D topview (xy). plot_stereonet(self, litho=None, planes=True, poles=True, single_plots=False, show_density=False) plot_topology(regular_grid: gempy.core.data.grid_modules.grid_types.RegularGrid, edges, centroids, direction='y', ax=None, scale=True, label_kwargs=None, edge_kwargs=None) Plot the topology adjacency graph in 2-D. Args: geo_model ([type]): GemPy geomodel instance. edges (Set[Tuple[int, int]]): Set of topology edges. centroids (Dict[int, Array[int, 3]]): Dictionary of topology id's and their centroids. direction (Union["x", "y", "z", optional): Section direction. Defaults to "y". label_kwargs (dict, optional): Keyword arguments for topology labels. Defaults to None. edge_kwargs (dict, optional): Keyword arguments for topology edges. Defaults to None. DATA __all__ = ['plot_2d', 'plot_3d', 'plot_section_traces', 'plot_topology... VERSION 2024.2.0.2 FILE f:\pythonproject\gempy-main.venv\lib\site-packages\gempy_viewer\__init__.py Help on package gempy.API in gempy: NAME gempy.API - # Initialization API PACKAGE CONTENTS _version compute_API examples_generator faults_API gp2_gp3_compatibility (package) grid_API implicit_functions initialization_API io_API map_stack_to_surfaces_API FUNCTIONS add_orientations(geo_model: gempy.core.data.geo_model.GeoModel, x: Sequence[float], y: Sequence[float], z: Sequence[float], elements_names: Sequence[str], pole_vector: Optional[Sequence[numpy.ndarray]] = None, orientation: Optional[Sequence[numpy.ndarray]] = None, nugget: Optional[Sequence[float]] = None) -> gempy.core.data.structural_frame.StructuralFrame Add orientation data to the geological model. This function adds orientation data to the specified geological elements in the model. The orientation can be provided directly as pole vectors or as orientation angles (azimuth, dip, polarity). Optional nugget values can also be specified for each orientation point. Args: geo_model (GeoModel): The geological model to which the orientations will be added. x (Sequence[float]): Sequence of x-coordinates for the orientation points. y (Sequence[float]): Sequence of y-coordinates for the orientation points. z (Sequence[float]): Sequence of z-coordinates for the orientation points. elements_names (Sequence[str]): Sequence of element names corresponding to each orientation point. pole_vector (Optional[Sequence[np.ndarray]]): Sequence of pole vectors for the orientation points. orientation (Optional[Sequence[np.ndarray]]): Sequence of orientation angles (azimuth, dip, polarity) for the orientation points. nugget (Optional[Sequence[float]]): Sequence of nugget values for each orientation point. If not provided, a default value will be used for all points. Returns: StructuralFrame: The updated structural frame of the geological model. Raises: ValueError: If neither pole_vector nor orientation is provided, or if the length of the nugget sequence does not match the lengths of the other input sequences. add_structural_group(model: gempy.core.data.geo_model.GeoModel, group_index: int, structural_group_name: str, elements: list[gempy.core.data.structural_element.StructuralElement], structural_relation: gempy_engine.core.data.stack_relation_type.StackRelationType, fault_relations: gempy.core.data.structural_group.FaultsRelationSpecialCase = <FaultsRelationSpecialCase.OFFSET_ALL: 3>) -> gempy.core.data.structural_frame.StructuralFrame add_surface_points(geo_model: gempy.core.data.geo_model.GeoModel, x: Sequence[float], y: Sequence[float], z: Sequence[float], elements_names: Sequence[str], nugget: Optional[Sequence[float]] = None) -> gempy.core.data.structural_frame.StructuralFrame Add surface points to the geological model. This function adds surface points to the specified geological elements in the model. The points are grouped by element names, and optional nugget values can be specified for each point. Args: geo_model (GeoModel): The geological model to which the surface points will be added. x (Sequence[float]): Sequence of x-coordinates for the surface points. y (Sequence[float]): Sequence of y-coordinates for the surface points. z (Sequence[float]): Sequence of z-coordinates for the surface points. elements_names (Sequence[str]): Sequence of element names corresponding to each surface point. nugget (Optional[Sequence[float]]): Sequence of nugget values for each surface point. If not provided, a default value will be used for all points. Returns: StructuralFrame: The updated structural frame of the geological model. Raises: ValueError: If the length of the nugget sequence does not match the lengths of the other input sequences. calculate_gravity_gradient(centered_grid: gempy_engine.core.data.centered_grid.CenteredGrid, ugal=True) -> numpy.ndarray compute_model(gempy_model: gempy.core.data.geo_model.GeoModel, engine_config: Optional[gempy.core.data.gempy_engine_config.GemPyEngineConfig] = None) -> gempy_engine.core.data.solutions.Solutions Compute the geological model given the provided GemPy model. Args: gempy_model (GeoModel): The GemPy model to compute. engine_config (Optional[GemPyEngineConfig]): Configuration for the computational engine. Defaults to None, in which case a default configuration will be used. Raises: ValueError: If the provided backend in the engine_config is not supported. Returns: Solutions: The computed geological model. compute_model_at(gempy_model: gempy.core.data.geo_model.GeoModel, at: numpy.ndarray, engine_config: Optional[gempy.core.data.gempy_engine_config.GemPyEngineConfig] = None) -> numpy.ndarray Compute the geological model at specific coordinates. Note: This function sets a custom grid and computes the model so be wary of side effects. Args: gempy_model (GeoModel): The GemPy model to compute. at (np.ndarray): The coordinates at which to compute the model. engine_config (Optional[GemPyEngineConfig], optional): Configuration for the computational engine. Defaults to None, in which case a default configuration will be used. Returns: np.ndarray: The computed geological model at the specified coordinates. create_data_legacy(*, project_name: str = 'default_project', extent: Union[list, numpy.ndarray] = None, resolution: Union[list, numpy.ndarray] = None, path_i: str = None, path_o: str = None) -> gempy.core.data.geo_model.GeoModel create_geomodel(*, project_name: str = 'default_project', extent: Union[list, numpy.ndarray] = None, resolution: Union[list, numpy.ndarray] = None, refinement: int = 1, structural_frame: gempy.core.data.structural_frame.StructuralFrame = None, importer_helper: gempy.core.data.importer_helper.ImporterHelper = None) -> gempy.core.data.geo_model.GeoModel Initializes and returns a GeoModel instance with specified parameters. Args: project_name (str, optional): The name of the project. Defaults to 'default_project'. extent (Union[List, np.ndarray], optional): The 3D extent of the grid. Must be provided if resolution is specified. Defaults to None. resolution (Union[List, np.ndarray], optional): The resolution of the grid. If None, an octree grid will be initialized. Defaults to None. refinement (int, optional): The level of refinement for the octree grid. Defaults to 1. structural_frame (StructuralFrame, optional): The structural frame of the GeoModel. Either this or importer_helper must be provided. Defaults to None. importer_helper (ImporterHelper, optional): Helper object for importing structural elements. Either this or structural_frame must be provided. Defaults to None. Returns: GeoModel: The initialized GeoModel object. Raises: ValueError: If neither structural_frame nor importer_helper is provided. create_orientations_from_surface_points_coords(xyz_coords: numpy.ndarray, subset: Optional[numpy.ndarray] = None, element_name: Optional[str] = 'Generated') -> gempy.core.data.orientations.OrientationsTable delete_orientations() delete_surface_points() generate_example_model(example_model: gempy.core.data.enumerators.ExampleModel, compute_model: bool = True) -> gempy.core.data.geo_model.GeoModel map_stack_to_surfaces(gempy_model: gempy.core.data.geo_model.GeoModel, mapping_object: Union[dict[str, list[str]], dict[str, tuple]], set_series: bool = True, remove_unused_series=True) -> gempy.core.data.structural_frame.StructuralFrame Map stack (series) to surfaces by reorganizing elements between groups in a GeoModel's structural frame. This function reorganizes structural elements (surfaces) based on a mapping object and updates the structural frame of the GeoModel. It can also create new series and remove unused ones. Args: gempy_model (GeoModel): The GeoModel object whose structural frame is to be modified. mapping_object (Union[dict[str, list[str]] | dict[str, tuple]]): Dictionary mapping group names to element names. set_series (bool, optional): If True, creates new series for groups not present in the GeoModel. Defaults to True. remove_unused_series (bool, optional): If True, removes groups without any elements. Defaults to True. Returns: StructuralFrame: The updated StructuralFrame object. modify_orientations(geo_model: gempy.core.data.geo_model.GeoModel, slice: Union[int, slice, NoneType] = None, **orientation_field: Union[float, numpy.ndarray]) -> gempy.core.data.structural_frame.StructuralFrame Modifies specified fields of all orientations in the structural frame. The keys of the orientation_field dictionary should match the field names in the orientations (e.g., "X", "Y", "Z", "G_x", "G_y", "G_z", "nugget"). Args: geo_model (GeoModel): The GeoModel instance to modify. slice (Optional[Union[int, slice]]): The slice of orientations to modify. If None, all orientations will be modified. Keyword Args: X (Union[float, np.ndarray]): X coordinates of the orientations. Y (Union[float, np.ndarray]): Y coordinates of the orientations. Z (Union[float, np.ndarray]): Z coordinates of the orientations. azimuth (Union[float, np.ndarray]): Azimuth angles of the orientations. dip (Union[float, np.ndarray]): Dip angles of the orientations. polarity (Union[float, np.ndarray]): Polarity values of the orientations. G_x (Union[float, np.ndarray]): X component of the gradient vector. G_y (Union[float, np.ndarray]): Y component of the gradient vector. G_z (Union[float, np.ndarray]): Z component of the gradient vector. nugget (Union[float, np.ndarray]): Nugget value of the orientations. Returns: StructuralFrame: The modified structural frame. modify_surface_points(geo_model: gempy.core.data.geo_model.GeoModel, slice: Union[int, slice, NoneType] = None, elements_names: Optional[Sequence[str]] = None, **surface_points_field: Union[float, numpy.ndarray]) -> gempy.core.data.structural_frame.StructuralFrame Modifies specified fields of all surface points in the structural frame. The keys of the surface_points_field dictionary should match the field names in the surface points (e.g., "X", "Y", "Z", "nugget"). Args: geo_model (GeoModel): The GeoModel instance to modify. slice (Optional[Union[int, slice]]): The slice of surface points to modify. If None, all surface points will be modified. Keyword Args: X (Union[float, np.ndarray]): X coordinates of the surface points. Y (Union[float, np.ndarray]): Y coordinates of the surface points. Z (Union[float, np.ndarray]): Z coordinates of the surface points. nugget (Union[float, np.ndarray]): Nugget value of the surface points. Returns: StructuralFrame: The modified structural frame. remove_element_by_name(model: gempy.core.data.geo_model.GeoModel, element_name: str) -> gempy.core.data.structural_frame.StructuralFrame remove_structural_group_by_index(model: gempy.core.data.geo_model.GeoModel, group_index: int) -> gempy.core.data.structural_frame.StructuralFrame remove_structural_group_by_name(model: gempy.core.data.geo_model.GeoModel, group_name: str) -> gempy.core.data.structural_frame.StructuralFrame set_active_grid(grid: gempy.core.data.grid.Grid, grid_type: list[gempy.core.data.grid.Grid.GridTypes], reset: bool = False) set_centered_grid(grid: gempy.core.data.grid.Grid, centers: numpy.ndarray, resolution: Sequence[float], radius: Union[float, Sequence[float]]) set_custom_grid(grid: gempy.core.data.grid.Grid, xyz_coord: numpy.ndarray) set_fault_relation(frame: Union[gempy.core.data.geo_model.GeoModel, gempy.core.data.structural_frame.StructuralFrame], rel_matrix: numpy.ndarray) -> gempy.core.data.structural_frame.StructuralFrame Sets the fault relations in the structural frame of the GeoModel. Args: frame (Union[GeoModel, StructuralFrame]): GeoModel or its StructuralFrame to be modified. rel_matrix (np.ndarray): Fault relation matrix to be set. Returns: StructuralFrame: The updated StructuralFrame object. set_is_fault(frame: Union[gempy.core.data.geo_model.GeoModel, gempy.core.data.structural_frame.StructuralFrame], fault_groups: Union[list[str], list[gempy.core.data.structural_group.StructuralGroup]], faults_relation_type: gempy.core.data.structural_group.FaultsRelationSpecialCase = <FaultsRelationSpecialCase.OFFSET_FORMATIONS: 1>, change_color: bool = True) -> gempy.core.data.structural_frame.StructuralFrame Sets given groups as fault in the structural frame of the GeoModel. It can optionally change the color of these groups. Args: frame (Union[GeoModel, StructuralFrame]): GeoModel or its StructuralFrame to be modified. fault_groups (Union[list[str], list[StructuralGroup]]): Groups to be set as faults. faults_relation_type (FaultsRelationSpecialCase, optional): Faults relation type to be set. Defaults to FaultsRelationSpecialCase.OFFSET_FORMATIONS. change_color (bool, optional): If True, changes the color of the fault groups. Defaults to True. Returns: StructuralFrame: The updated StructuralFrame object. set_is_finite_fault(self, series_fault=None, toggle: bool = True) set_section_grid(grid: gempy.core.data.grid.Grid, section_dict: dict) set_topography_from_arrays(grid: gempy.core.data.grid.Grid, xyz_vertices: numpy.ndarray) set_topography_from_file(grid: gempy.core.data.grid.Grid, filepath: str, crop_to_extent: Optional[Sequence] = None) set_topography_from_random(grid: gempy.core.data.grid.Grid, fractal_dimension: float = 2.0, d_z: Optional[Sequence] = None, topography_resolution: Optional[Sequence] = None) Sets the topography of the grid using a randomly generated topography. Args: grid (Grid): The grid object on which to set the topography. fractal_dimension (float, optional): The fractal dimension of the random topography. Defaults to 2.0. d_z (Union[Sequence, None], optional): The sequence of elevation increments for the random topography. If None, a default sequence will be used. Defaults to None. topography_resolution (Union[Sequence, None], optional): The resolution of the random topography. If None, the resolution of the grid's regular grid will be used. Defaults to None. Returns: The topography object that was set on the grid. Example: >>> grid = Grid() >>> set_topography_from_random(grid, fractal_dimension=1.5, d_z=[0.1, 0.2, 0.3], topography_resolution=[10, 10]) Note: If topography_resolution is None, the resolution of the grid's regular grid will be used. If d_z is None, a default sequence of elevation increments will be used. set_topography_from_subsurface_structured_grid(grid: gempy.core.data.grid.Grid, struct: 'subsurface.StructuredData') structural_elements_from_borehole_set(borehole_set: 'subsurface.core.geological_formats.BoreholeSet', elements_dict: dict) -> list[gempy.core.data.structural_element.StructuralElement] Creates a list of StructuralElements from a BoreholeSet. Args: borehole_set (subsurface.core.geological_formats.BoreholeSet): The BoreholeSet object containing the boreholes. elements_dict (dict): A dictionary containing the properties of the structural elements to be created. Returns: list[StructuralElement]: A list of StructuralElement objects created from the borehole set. Raises: ValueError: If a top lithology ID specified in `elements_dict` is not found in the borehole set. DATA __all__ = ['create_data_legacy', 'create_geomodel', 'structural_elemen... FILE f:\pythonproject\gempy-main.venv\lib\site-packages\gempy\api\__init__.py Help on package gempy.core in gempy: NAME gempy.core PACKAGE CONTENTS color_generator data (package) FILE f:\pythonproject\gempy-main.venv\lib\site-packages\gempy\core\__init__.py Help on package gempy_engine.API in gempy_engine: NAME gempy_engine.API PACKAGE CONTENTS _version dual_contouring (package) interp_single (package) model (package) server (package) FILE f:\pythonproject\gempy-main.venv\lib\site-packages\gempy_engine\api\__init__.py Help on package gempy_engine: NAME gempy_engine PACKAGE CONTENTS API (package) _version config core (package) modules (package) optional_dependencies plugins (package) VERSION 2024.2.0 FILE f:\pythonproject\gempy-main.venv\lib\site-packages\gempy_engine\__init__.py Process finished with exit code 0
11-07
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值